//WITH FILTER

/**
 *	@author: Francis Germiline Veto
 *	date created: December 29, 2005
 *	@ver: 1.01.08
 * 	change history:
 *		February 12, 2006 - kit
 *			adjusted to the Vector nature of TExtChunk
 *			included flushUnusedSentences() and getRequiredStrings(Vector, Vector)
 *		February 18, 2006 - kit
 *			began adopting the refinement of templates (ie: beyond simple match)
 *		March 19, 2006 - kit
 *			began matching chunks by exploring beyond simple match
 *		June 21, 2006 - kit
 *			cleaned up code in preparation for final analysis
 *		July 9, 2006 - kit
 *			converted long codes into subfunctions to optimize memory usage
 */

/* UPDATE: 021506
 *	Accounted for the punctuation mark at the end of every sentence.
 *	Affected functions:
 *		findMatchingUnusedSentence()
 *		deriveTemplate(AS,AS)
 *		deriveTemplate(AS,V)
 *	Filtering matching templates in refineTemplate(AS,V) done. Null chunk
 *		matching already handled.
 *	New chunk insertion issue in updateDatabase(T,T,H) resolved.
 * UPDATE: 021806
 *	Added updateDatabaseWithRefinement(V,V,V,V,b). This is still untested.
 *	Prepared refineTemplate(AS,V) for future adoption of the refinement
 *		algorithm.
 * UPDATE: 022506
 *	Chunk aligning in deriveTemplate(AS,AS) finally resolved.
 *	Chunk matching per subchunk word issue addressed.
 * UPDATE: 030406
 *	[M.N] and [M] duplicate chunk checking resolved.
 *	Single quotes for values in SQL statements now handled.
 * UPDATE: 031306
 *	Fixed to fit with the adjustments to integration with the GUI. Changes are
 *		mostly about differing template formats and database consistency checks.
 * UPDATE: 032206
 *	Templates now do not have ending punctuation marks.
 * UPDATE: 032406
 *	Modified learning sequence from 'Template->Chunk->Sentence' to
 *		'Template->Sentence->Chunk'.
 * UPDATE: 032806
 *	Subchunk exploration for matching in learning now implemented. This match,
 *		however, only provides for one chunk per template.
 * UPDATE: 051706
 *	Refined learning from chunks; now able to formulate templates with elements
 *		substituted by many chunks.
 * UPDATE: 051906
 *	Improved score heuristic of generating template from chunks; it does not
 *		just rely on the score based on number of Strings, but also on the
 *		number of score difference between source and target language templates.
 * UPDATE: 062406
 *	Made sure that the selection of the combination of chunks used to formulate
 *		a template would not produce one that contains only 'function' words.
 *	Update database upgraded to count number of constants in template.
 * UPDATE: 070406
 *	Made sure that no templates use chunks with the same String constitution. Also,
 *		made sure that learning from chunks avoids overdeletion of conflict
 *		chunks from the base set Vector.
 */

package text.learning;

import java.util.Vector;
import java.util.Hashtable;
import java.util.Enumeration;
import java.util.Collection;
import java.util.StringTokenizer;
import java.util.Iterator;
import java.sql.ResultSet;
import java.sql.SQLException;

import text.ia.TExtAligner;
import text.obj.AlignedChunk;
import text.obj.AlignedTemplate;
import text.obj.AlignedSentence;
import text.obj.ChunkPair;
import text.obj.TExtChunk;
import text.obj.TExtSentence;
import text.obj.TExtTemplate;
import text.util.DBConnector;
import text.util.TExtLearnerUtility;
import text.util.TExtUtility;
import javax.swing.JOptionPane;

public class TExtLearner implements Learner {
	
	private final int _nCeilingScoreHeuristic = 99999;
	
	private TExtChunkAligner txtChunkAlign;
	private Vector vLearningTracer;
	private Vector vUnmatchedSentences;
	private boolean bSourceIsFilipino;
	private TExtLearnerUtility tlu;
	private ChunkRefiner cr;
	 
	
	private Vector vCPObjects;
	
	//current setting: version 1.0f
	public static boolean doSTTL = true;
	public static boolean doDTTL = true;
	public static boolean doChunkRefinement = true;
	public static boolean doDTC = true;
	
	

	
	/**
	 * Initializes all class variables and prepares them for usage
	 * during the learning process.
	 *
	 * @param Vector aligned sentences
	 */
	public void initiateTemplateLearning(Vector vAlignedSentences,
		boolean bSourceIsFilipino) {
		
		if(vUnmatchedSentences == null)	
			vUnmatchedSentences = new Vector(1);
		if(vLearningTracer == null)	
			vLearningTracer = new Vector(1);

		this.bSourceIsFilipino = bSourceIsFilipino;
			// a pre-learning step, as with all future class declaration
			// variable initializations
		//loadUnusedSentences();


		tlu = new TExtLearnerUtility(this.bSourceIsFilipino);
		cr = new ChunkRefiner(bSourceIsFilipino, tlu);

		
		learnTemplate(vAlignedSentences);
	}

	/**
	 * Tries to learn a new template using the aligned sentence passed
	 * from initiateTemplateLearning(Vector).
	 *
	 * @see initiateTemplateLearning(Vector)
	 *
	 * @param Vector aligned sentences
	 */
	protected void learnTemplate(Vector vAlignedSentences) {
		AlignedSentence alMatchingUnusedSentence;
	
		// Exhaustive solution. Worst-case scenario solution.
	//	for(int a=0; a<vAlignedSentences.size(); a++) {
		while(vAlignedSentences.size() > 0){

			boolean isSuccessful = false;
		//	AlignedSentence alCurrent = (AlignedSentence)vAlignedSentences.get(a);
			AlignedSentence alCurrent = (AlignedSentence)vAlignedSentences.remove(0);
			if(bSourceIsFilipino)
				alCurrent.setSourceToFilipino(true);
			else
				alCurrent.setSourceToFilipino(false);

			//vLearningTracer.addElement("TR");
			TExtTemplateRefiner refiner = new TExtTemplateRefiner(bSourceIsFilipino, tlu);
			isSuccessful = refiner.startRefinement(alCurrent);

			if(!isSuccessful) {
				//vLearningTracer.removeElementAt(vLearningTracer.size()-1);
				//System.out.println("There are no matching templates.");
				
				alMatchingUnusedSentence = null;
				alMatchingUnusedSentence = findMatchingUnusedSentence(alCurrent);
				
				Vector vFailureBackup = new Vector(1);
				boolean bSucceededAtLeastOnce = false;
				while(alMatchingUnusedSentence != null) {

					isSuccessful = false;
					vLearningTracer.addElement("DTS");
					try{
						isSuccessful = deriveTemplate(alCurrent, alMatchingUnusedSentence);
					}catch(Exception e){
						e.printStackTrace();
						System.exit(0);
					}

						/* An aligned sentence from the Vector of unused
						 * sentences has been found. A template is derived
						 * from it and the aligned sentence being learned.
						 */
					
					if(isSuccessful) {
						vUnmatchedSentences.remove(alMatchingUnusedSentence);
						bSucceededAtLeastOnce = true;
					} else {
						vLearningTracer.removeElementAt(vLearningTracer.size()-1);
						vUnmatchedSentences.remove(alMatchingUnusedSentence);
						vFailureBackup.addElement(alMatchingUnusedSentence);
						/* If there was a sentence match but no proper template
						 * could be derived correctly from that sentence then it
						 * is removed temporarily from the Vector of unmatched
						 * sentences and transfered to the backup Vector.
						 * This is done to prevent repetitive match/infinite loop.
						 */
					}
					
					alMatchingUnusedSentence = null;
					alMatchingUnusedSentence = findMatchingUnusedSentence(alCurrent);
				}
				
				if(!vFailureBackup.isEmpty()) {
					vUnmatchedSentences.addAll(vFailureBackup);
					vFailureBackup.clear();

				}
				if(!bSucceededAtLeastOnce) {
					Vector vMatchingChunks = findMatchingChunks(alCurrent);
					vLearningTracer.addElement("DTC");
					if(vMatchingChunks.size()!=0 || vCPObjects.size()!=0){
						if (doDTC)
						isSuccessful = deriveTemplate(alCurrent, vMatchingChunks);
					}
						
					if(!isSuccessful) {
						vLearningTracer.removeElementAt(vLearningTracer.size()-1);
						
						String strSource = alCurrent.getSource().toString(),
							strTarget = alCurrent.getTarget().toString();
						
						boolean bDuplicateFound = false;
						for(Iterator it = vUnmatchedSentences.iterator(); 
							it.hasNext() && !bDuplicateFound; ) {

							AlignedSentence alTemp = (AlignedSentence)it.next();
							
							String strSentS = alTemp.getSource().toString(),
								strSentT = alTemp.getTarget().toString();
							
							if(strSource.equals(strSentS) && strTarget.equals(strSentT))
								bDuplicateFound = true;
						}
						
						if(!bDuplicateFound)
							vUnmatchedSentences.add(alCurrent);

					}
				}
			}else { //successful TR
				Vector vTRTrace = refiner.getTRTrace();
				for(int nTraceCnt = 0; vTRTrace != null && nTraceCnt < vTRTrace.size(); nTraceCnt++) {
					vLearningTracer.addElement(vTRTrace.get(nTraceCnt));
				}
			}
			
	//	JOptionPane.showMessageDialog(null, "unused -->" + vUnmatchedSentences.size());
		}
		
		storeUnusedSentences();
	//System.out.println("FINAL TRACER:"+vLearningTracer.toString());
		//flushUnusedSentences();
	}
	
	/**
	 * Finds the various chunks with elements that match objects
	 * in the parameter AlignedSentence alTemp.
	 * 
	 * Returns the vector of aligned chunks.
	 *
	 * @param AlignedSentence an aligned sentence to match a chunk with
	 * @return Vector aligned chunks matching the aligned sentence
	 */
	protected Vector findMatchingChunks(AlignedSentence alTemp) {
		Vector vMatchingChunks = new Vector(1);
//		vCMObjMemory = new Vector(1);
		vCPObjects = new Vector(1);
		
		String strStmt = new String();
		ResultSet rsChunks;
				
		// Exhaustive solution. Worst-case scenario solution.
		TExtSentence senSource = alTemp.getSource(), senTarget = alTemp.getTarget();
		Vector vTokenS = (Vector)((Vector)senSource.getWords()).clone(),
			vTokenT = (Vector)((Vector)senTarget.getWords()).clone();

		StringBuffer sbSource = new StringBuffer(" "), 
			sbTarget = new StringBuffer(" ");
		for(byte i=0; i<vTokenS.size(); i++)
			sbSource.append(vTokenS.get(i).toString()).append(' ');
		for(byte j=0; j<vTokenT.size(); j++)
			sbTarget.append(vTokenT.get(j).toString()).append(' ');
		
		vTokenS.remove(vTokenS.size()-1);
		vTokenT.remove(vTokenT.size()-1);
		
		String strSourceTable = new String(), strTargetTable = new String(),
			strSourceCW = new String(), strTargetCW = new String();
		if(bSourceIsFilipino) {
			strSourceTable = "chunkFilipino";
			strTargetTable = "chunkEnglish";
			strSourceCW = "compIDFilipino";
			strTargetCW = "compIDEnglish";
		}
		else {
			strSourceTable = "chunkEnglish";
			strTargetTable = "chunkFilipino";
			strSourceCW = "compIDEnglish";
			strTargetCW = "compIDFilipino";
		}
		strStmt = "Select * From Chunks Where " + strSourceTable;
		for(int a=0; a<vTokenS.size(); a++) {
			String strWord = (String)vTokenS.get(a);
	//System.out.println(strStmt + "='" + strWord.replace("'","''") + "'");
			rsChunks = DBConnector.select(strStmt + "='" 
				+ strWord.replace("'","''") + "'");

//EXACT MATCH BEGINS HERE	--> for n retrieved chunks, n templates	
			try {
				while(rsChunks.next()) {
					boolean bMatchFound = false;
					String strTargetC = rsChunks.getString(strTargetTable);
					String strSourceC = rsChunks.getString(strSourceTable);
					String strDomainC = rsChunks.getString("domain");
					String strCWSource = rsChunks.getString(strSourceCW);
					String strCWTarget = rsChunks.getString(strTargetCW);
					
	//System.out.println("'"+sbSource.toString()+"'"+sbTarget.toString()+"'");
	//System.out.println("-"+strSourceC+"-"+strTargetC+"-");
					if(sbSource.toString().toLowerCase().contains(
						" "+strSourceC.toLowerCase()+" ")
						&& sbTarget.toString().toLowerCase().contains(
							" "+strTargetC.toLowerCase()+" ")) {
						TExtChunk cSource = new TExtChunk(strSourceC, strDomainC, strCWSource),
							cTarget = new TExtChunk(strTargetC, strDomainC, strCWTarget);
							
				// for compound words	
						cSource = tlu.adjustChunkCompound(cSource);
						cTarget = tlu.adjustChunkCompound(cTarget);
				// end for compound words			
						vMatchingChunks.add(new AlignedChunk(cSource, cTarget));
					}
				}
			} catch(SQLException sqle) {
				System.err.println("Chunk Result Set error:"+sqle.getMessage());
			}finally{
				
			}
			
			try {
				rsChunks.close();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			
			String strWhere = new String();
			if(a==0)
				strWhere = new String("Where " + strSourceTable + " Like '" 
					+ strWord.replace("'","''") + " %'");
			else if(a==vTokenS.size()-1)
				strWhere = new String("Where " + strSourceTable + " Like '% " 
					+ strWord.replace("'","''") + "'");
			else
				strWhere = new String("Where " + strSourceTable + " Like '% " 
					+ strWord.replace("'","''") + " %' Or " + strSourceTable
					+ " Like '% " + strWord.replace("'","''") + "' Or " 
					+ strSourceTable + " Like '" + strWord.replace("'","''") 
					+ " %'");

//SUBCHUNK EXPLORATION MATCH CHECKING BEGINS HERE			
			rsChunks = DBConnector.select("Select * From Chunks " + strWhere);
			try {
				while(rsChunks.next()) {
					String strSourceC = rsChunks.getString(strSourceTable);
		//System.out.println(strWord+">>"+strSourceC);
					String strTargetC = rsChunks.getString(strTargetTable);
					String strDomainC = rsChunks.getString("domain");
		//System.out.println(strSourceC+"\\"+strTargetC+"\\"+strDomainC);
					
					String strCWSource = rsChunks.getString(strSourceCW);
					String strCWTarget = rsChunks.getString(strTargetCW);
					TExtChunk cSource = new TExtChunk(strSourceC, strDomainC, 
						strCWSource), cTarget = new TExtChunk(strTargetC, 
						strDomainC, strCWTarget);
						
			// for compound words
					cSource = tlu.adjustChunkCompound(cSource);
					cTarget = tlu.adjustChunkCompound(cTarget);
			// end for compound words
			
			/* At this point, the TExtChunk objects must have compound words
			 *	put together into one token only.
			 */
					int nTracker1 = a, nPtr1 = 0;
					while(nPtr1<cSource.size() && nTracker1<vTokenS.size()
						&& cSource.elementAt(nPtr1) instanceof String 
						&& cSource.elementAt(nPtr1).toString()
						.equalsIgnoreCase(vTokenS.elementAt(nTracker1).toString())) {
						nTracker1++;
						nPtr1++;
					}

//exact match din, pero nasasama cya sa filtering for best chunk matching (konti constant)
					if(nPtr1==cSource.size()) {
						boolean bMatchFound = false;
						for(int c=0; !bMatchFound && c<vTokenT.size(); c++) {
							String strCheck = (String)vTokenT.get(c);
							if(strTargetC.startsWith(strCheck)) {
								int nTracker2 = c, nPtr2 = 0;
								while(nPtr2<cTarget.size() && nTracker2<vTokenT.size()
									&& cTarget.elementAt(nPtr2) instanceof String 
									&& cTarget.elementAt(nPtr2).toString()
									.equalsIgnoreCase(vTokenT.elementAt(nTracker2).toString())) {
									nTracker2++;
									nPtr2++;
								}
								if(nPtr2==cTarget.size())
									bMatchFound = true;
							}
						}
						if(bMatchFound)
							vMatchingChunks.add(new AlignedChunk(cSource, cTarget));
					} else {
		//System.out.println("SUBCHUNK MATCH SEARCHING");
						//subchunk exploration; only source side so far
						ChunkMiner cmObject = new ChunkMiner(bSourceIsFilipino, tlu),
							cmObject2 = new ChunkMiner(bSourceIsFilipino, tlu);
						
						boolean bChunkMatcherAdded = false;
						boolean bCPAdded = false;
						// SOURCE
						int nTracker3 = 0;
						boolean bPreviousWasChunk = false;
						Vector vWhole = new Vector(1), vPart = new Vector(1);
						boolean bMatchCandidate = true;
						Vector vExampleS = (Vector)vTokenS.clone();
						Vector vChunkDom = new Vector(1);
						boolean bChunkThenStringFirst = true; // to replace d==1
						for(int d=0; d<cSource.size() && bMatchCandidate; d++) {
							Object oScan = cSource.elementAt(d);
							//System.out.println("oScan("+oScan.toString()+")");
							
							if(oScan instanceof String) {
								if(d==0) //ins
									bChunkThenStringFirst = false; //ins
								if(!bPreviousWasChunk) {
									int e = nTracker3;
									while(e<vExampleS.size() &&
										!oScan.toString().equalsIgnoreCase(vExampleS.elementAt(e).toString())) 
										e++;
									if(e<vExampleS.size() &&
										oScan.toString().equalsIgnoreCase(vExampleS.elementAt(e).toString())) {
										vWhole.addElement(oScan.toString());
										nTracker3 = e+1;
									} else
										bMatchCandidate = false;
								} else {
								//	if(d==1) { //meaning the previous chunk was the first
									if(bChunkThenStringFirst) { //mod
										int base = nTracker3;
										boolean bFound = false;
										Vector vNew = new Vector(1);
										String strComp = oScan.toString();
					//System.out.println("toCompare:"+strComp);
										int n = nTracker3;
										while(n+1<vExampleS.size() &&
											!vExampleS.elementAt(n).toString().equalsIgnoreCase(strComp)) 
											n++;
										if(vExampleS.elementAt(n).toString().equalsIgnoreCase(strComp))
											nTracker3 = n;
										while(!bFound && base < nTracker3) {
						//System.out.println("--"+base+"-->>"+nTracker3);
											for(int o=base; o < nTracker3; o++)
												vNew.addElement(vExampleS.elementAt(o).toString());
											cmObject.clearData();
											//System.out.println("to pass E:"+vNew.toString());
											Object oSample; //ins
											if(vChunkDom.size()==1) //mod
												oSample = cmObject.exploreChunk((Vector)vNew.clone(),
													vChunkDom.elementAt(0).toString(), true); //mod
											else //mod
												oSample = cmObject.exploreWithAdjacentChunks(
													(Vector)vNew.clone(), vChunkDom, true); //mod
//System.gc();											
											if(oSample instanceof ChunkPair) {
												String strSour = ((ChunkPair)oSample).getSourceStr();
						//System.out.println("string:"+strSour);
												if(!strSour.equals("") && !strSour.contains("[")) {
													vWhole.addAll(vNew);
													vWhole.add(oScan.toString());
													vChunkDom.clear(); //ins
													nTracker3++;
													bFound = true;
												}
											}
											vNew.clear();
											base++;
						//System.out.println("^^"+bFound+"--"+base);
										}
										bChunkThenStringFirst = false; //ins
									} else {
										int f = nTracker3;
						//System.out.println(nTracker3+"%%%"+f+"%%%"+vExampleS.elementAt(f).toString());
										while(f<vExampleS.size() &&
											!oScan.toString().equalsIgnoreCase(vExampleS.elementAt(f).toString())) {
											vPart.addElement(vExampleS.elementAt(f).toString());
											f++;
										}
		//				System.out.println(nTracker3+"%%%"+f+"%%%"+vExampleS.elementAt(f).toString());
										if(f<vExampleS.size() &&
											oScan.toString().equalsIgnoreCase(vExampleS.elementAt(f).toString())) {
											vWhole.addAll(vPart);
											vWhole.addElement(oScan.toString());
						//System.out.println(vWhole.toString());
											nTracker3 = f+1;
										} else
											bMatchCandidate = false;
										vPart.clear();
										vChunkDom.clear(); //ins
									}									
								}
								bPreviousWasChunk = false;
							} else {
								vChunkDom.addElement(oScan.toString()
									.substring(1,oScan.toString().length()-1)); //ins
								if(d == cSource.size()-1) {
								// TO ADJUST part 1 START, as per 'chunk learning 060406-4.txt'
									int padding = 0;
									boolean bFound = false;
									Vector vNew = new Vector(1);
									while(!bFound && nTracker3<vExampleS.size()-padding) {
										for(int g=nTracker3; g<vExampleS.size()-padding; g++)
											vNew.addElement(vExampleS.elementAt(g).toString());
										cmObject.clearData();
										//System.out.println("to pass A:"+vNew.toString());
										Object oSample; //ins
										if(vChunkDom.size()==1) //mod
											oSample = cmObject.exploreChunk((Vector)vNew.clone(),
												vChunkDom.elementAt(0).toString(), true); //mod
										else //mod
											oSample = cmObject.exploreWithAdjacentChunks(
												(Vector)vNew.clone(), vChunkDom, true); //mod
//System.gc();
										if(oSample instanceof ChunkPair){
											String strSour = ((ChunkPair)oSample).getSourceStr();
					//System.out.println("string:"+strSour);
											if(!strSour.equals("") && !strSour.contains("[")) {
					//System.out.println("vNew:"+vNew);
												vWhole.addAll(vNew);
												vChunkDom.clear(); //ins
												bFound = true;
											}
										} else {
					//System.out.println("failed:"+oSample.toString()+"-->"+vNew.toString());
										}
										vNew.clear();
										padding++;
									}
									// TO ADJUST part 1 END, as per 'chunk learning 060406-4.txt'
								}
								bPreviousWasChunk = true;
							}
							//System.out.println("vWhole{"+vWhole.toString()+"}");
						}
						if(bMatchCandidate) {
							//System.out.println("BMATCHCANDIDATE SOURCE");
							cmObject.clearData();
							//System.out.println("to pass B:'"+vWhole.toString()+"'");
							Object oTest = cmObject.exploreChunk(vWhole,
								strDomainC, true);
//System.gc();
							if(oTest instanceof ChunkPair) {
								//System.out.println("INSTANCE OF CHUNKPAIR SOURCE");
			//System.out.println("source string:/"+((ChunkPair)oTest).getSourceChunk()+"/");
								if(!((ChunkPair)oTest).getSourceStr().contains("[")) {
									//System.out.println("CONTAINS [ SOURCE");
									vCPObjects.addElement((ChunkPair)oTest);
			//System.out.println("source chunk:"+((ChunkPair)oTest).getSourceChunk()+"="+((ChunkPair)oTest).getSourceChunk().size());
									if(((ChunkPair)vCPObjects.elementAt(vCPObjects.size()-1))
										.equals((ChunkPair)oTest))
										bCPAdded = true;
								}
							} else
								continue;
						} else
							continue;
//						cmObject.disconnectDB();
						
						//TARGET
						int nTracker4 = 0;
						bPreviousWasChunk = false;
						vWhole.clear();
						vPart.clear();
						bMatchCandidate = true;
						Vector vExampleT = (Vector)vTokenT.clone();
						String strFirstDom = new String();
						vChunkDom = new Vector(1); // to replace strFirstDom
						bChunkThenStringFirst = true; // to replace h==1
						for(int h=0; h<cTarget.size() && bMatchCandidate; h++) {
							Object oScan = cTarget.get(h);
							//System.out.println("oScan("+oScan.toString()+")");
							
							//System.out.println("^^^^^^^^^" + oScan.toString());
							//System.out.println("^^^^^^^^^" + vExampleT);
							
							if(oScan instanceof String) {
								if(h==0) //ins
									bChunkThenStringFirst = false; //ins
								if(!bPreviousWasChunk) {
									int i = nTracker4;
									while(i<vExampleT.size() &&
										!oScan.toString().equalsIgnoreCase(vExampleT.elementAt(i).toString())) 
										i++;
									if(i<vExampleT.size() &&
										oScan.toString().equalsIgnoreCase(vExampleT.elementAt(i).toString())) {
										vWhole.addElement(oScan.toString());
										nTracker4 = i+1;
									} else
										bMatchCandidate = false;
									//System.out.println("---->BLAHBLAH!!!--->" + bMatchCandidate);
								} else {
								//	if(h==1) { //meaning the previous chunk was the first
									if(bChunkThenStringFirst) { //mod
										int base = nTracker4;
										boolean bFound = false;
										Vector vNew = new Vector(1);
										String strComp = oScan.toString();//cTarget.get(h+1).toString();
						//System.out.println("toCompare:"+strComp);
										int l = nTracker4;
										while(l+1<vExampleT.size() &&
											!vExampleT.elementAt(l).toString().equalsIgnoreCase(strComp)) 
											l++;
										if(vExampleT.elementAt(l).toString().equalsIgnoreCase(strComp))
											nTracker4 = l;
										while(!bFound && base < nTracker4) {
						//System.out.println("--"+base+"-->>"+nTracker4);
											for(int m=base; m < nTracker4; m++)
												vNew.addElement(vExampleT.elementAt(m).toString());
											cmObject2.clearData();
											//System.out.println("to pass F:"+vNew.toString());
											Object oSample; //ins
											if(vChunkDom.size()==1) //mod
												oSample = cmObject2.exploreChunk((Vector)vNew.clone(),
													vChunkDom.elementAt(0).toString(), false); //mod
											else //mod
												oSample = cmObject2.exploreWithAdjacentChunks(
													(Vector)vNew.clone(), vChunkDom, false); //mod
//System.gc();
											if(oSample instanceof ChunkPair) {
												String strTarg = ((ChunkPair)oSample).getTargetStr();
						//System.out.println("string:"+strTarg);
												if(!strTarg.equals("") && !strTarg.contains("[")) {
													vWhole.addAll(vNew);
													vWhole.add(oScan.toString());
													vChunkDom.clear(); //ins
													nTracker4++;
													bFound = true;
												}
											}
											vNew.clear();
											base++;
						//System.out.println("^^"+bFound+"--"+base);
										}
										bChunkThenStringFirst = false; //ins
									} else {
										int j = nTracker4;
						//System.out.println(nTracker4+"%%%"+j+"%%%"+vExampleT.elementAt(j).toString());
										while(j<vExampleT.size() &&
											!oScan.toString().equalsIgnoreCase(vExampleT.elementAt(j).toString())) {
											vPart.addElement(vExampleT.elementAt(j).toString());
											j++;
										}
			//			System.out.println(nTracker4+"%%%"+j+"%%%"+vExampleT.elementAt(j).toString());
										if(j<vExampleT.size() &&
											oScan.toString().equalsIgnoreCase(vExampleT.elementAt(j).toString())) {
											vWhole.addAll(vPart);
											vWhole.addElement(oScan.toString());
						//System.out.println(vWhole.toString());
											nTracker4 = j+1;
										} else
											bMatchCandidate = false;
										//System.out.println("<----BLAHBLAH!!!<---" + bMatchCandidate);
										vPart.clear();
										vChunkDom.clear(); //ins
									}									
								}
								bPreviousWasChunk = false;
							} else {
								vChunkDom.addElement(oScan.toString()
									.substring(1,oScan.toString().length()-1)); //ins
								if(h == cTarget.size()-1) {
									// TO ADJUST part 2 START, as per 'chunk learning 060406-4.txt'
									int padding = 0;
									boolean bFound = false;
									Vector vNew = new Vector(1);
									while(!bFound && nTracker4<vExampleT.size()-padding) {
					//System.out.println(">>"+nTracker4+"--"+padding);
										for(int k=nTracker4; k<vExampleT.size()-padding; k++)
											vNew.addElement(vExampleT.elementAt(k).toString());
										cmObject2.clearData();
										//System.out.println("to pass C:"+vNew.toString());
										Object oSample; //ins
										if(vChunkDom.size()==1) //mod
											oSample = cmObject2.exploreChunk((Vector)vNew.clone(),
												vChunkDom.elementAt(0).toString(), false); //mod
										else //mod
											oSample = cmObject2.exploreWithAdjacentChunks(
												(Vector)vNew.clone(), vChunkDom, false); //mod
//System.gc();
										if(oSample instanceof ChunkPair) {
											String strTarg = ((ChunkPair)oSample).getTargetStr();
					//System.out.println("string:"+strTarg);
											if(!strTarg.equals("") && !strTarg.contains("[")) {
					//System.out.println("vNew:"+vNew);
												vWhole.addAll(vNew);
												vChunkDom.clear(); //ins
												bFound = true;
											}
										} else {
					//System.out.println("failed:"+oSample.toString()+"-->"+vNew.toString());
										}
										vNew.clear();
										padding++;
					//System.out.println("^^"+bFound+"--"+padding);
									}
									// TO ADJUST part 2 END, as per 'chunk learning 060406-4.txt'
								} 
								bPreviousWasChunk = true;
							}
							//System.out.println("vWhole{"+vWhole.toString()+"}");
						}
						//System.out.println("BEFORE BMATCHCANDIDATE TARGET");
						if(bMatchCandidate) {
							//System.out.println("BMATCHCANDIDATE TARGET");
							cmObject2.clearData();
							//System.out.println("to pass D:'"+vWhole.toString()+"'");
							Object oTest = cmObject2.exploreChunk(vWhole,
								strDomainC, false);
//System.gc();								
							if(oTest instanceof ChunkPair) {
								//System.out.println("INSTANCE OF CHUNKPAIR TARGET");
			//System.out.println("target string:/"+((ChunkPair)oTest).getTargetStr()+"/");
								if(!((ChunkPair)oTest).getTargetStr().contains("[")) {
									//System.out.println("!CONTAINS [ TARGET");
									if(bCPAdded) {
										vCPObjects.addElement((ChunkPair)oTest);
			//System.out.println("target chunk:"+((ChunkPair)oTest).getTargetChunk()+"="+((ChunkPair)oTest).getTargetChunk().size());
										if(!((ChunkPair)vCPObjects.elementAt(vCPObjects.size()-1))
											.equals((ChunkPair)oTest))
											vCPObjects.removeElementAt(vCPObjects.size()-1);
									}
								}
							} else if(bCPAdded) 
								vCPObjects.removeElementAt(vCPObjects.size()-1);
						} else {
							if(bCPAdded)
								vCPObjects.removeElementAt(vCPObjects.size()-1);
						}
//						cmObject2.disconnectDB();
						
						
						//subchunk exploration
					}
				}
			} catch(SQLException sqle) {
				System.err.println("Chunk Result Set error:"+sqle.getMessage());
			}
			
			try {
				rsChunks.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		/* check whether a chunk from the database has a constant 
		 * belonging to the aligned sentence; 
		 * if so, add the chunk, else discard
		 */
		return vMatchingChunks;
	}
	
	/**
	 * Finds the various unmatched sentences with elements that match objects
	 * in the parameter Vector vAlignedSentence.
	 * 
	 * Returns the vector of matching sentences.
	 *
	 * @param AlignedSentence an aligned sentence to derive a template with
	 * @return AlignedSentence unused sentence matching the aligned sentence
	 */
	protected AlignedSentence findMatchingUnusedSentence(AlignedSentence alTemp) {
		AlignedSentence alMatch = null;
		
		TExtSentence sBase;
		if(alTemp.isSourceFilipino())
			if(bSourceIsFilipino)
				sBase = alTemp.getSource();
			else
				sBase = alTemp.getTarget();
		else
			if(bSourceIsFilipino)
				sBase = alTemp.getTarget();
			else
				sBase = alTemp.getSource();
		Vector vBaseWords = (Vector)((Vector)sBase.getWords()).clone();
		
		vBaseWords.remove(vBaseWords.size()-1);
		boolean bFoundMatch = false;
		for(int a=0; !bFoundMatch && a<vUnmatchedSentences.size(); a++) {
			
			AlignedSentence alCheck = (AlignedSentence)vUnmatchedSentences.get(a);
			TExtSentence sCheck;
			
			if(alCheck.isSourceFilipino())
				if(bSourceIsFilipino)
					sCheck = alCheck.getSource();
				else
					sCheck = alCheck.getTarget();
			else
				if(bSourceIsFilipino)
					sCheck = alCheck.getTarget();
				else
					sCheck = alCheck.getSource();
			Vector vCheckWords = (Vector)((Vector)sCheck.getWords()).clone();
			
			vCheckWords.remove(vCheckWords.size()-1);
			
			for(int b=0; !bFoundMatch && b<vBaseWords.size(); b++)
				for(int c=0; !bFoundMatch && c<vCheckWords.size(); c++) {
					if(vCheckWords.get(c).toString().equals(",") ||
						vCheckWords.get(c).toString().equals("'") ||
						vCheckWords.get(c).toString().equals("\""))
						continue;
					if(vBaseWords.get(b).equals(vCheckWords.get(c))) {
						alMatch = alCheck;
						bFoundMatch = true;
					}
				}
	}
	
		if(!bFoundMatch) {
			String strSourceTable, strTargetTable;
			if(bSourceIsFilipino) {
				strSourceTable = "sentenceFilipino";
				strTargetTable = "sentenceEnglish";
			} else {
				strSourceTable = "sentenceEnglish";
				strTargetTable = "sentenceFilipino";
			}
			
			String strStmt = "Select * From UnusedSentences ";
			
			for(int d=0; !bFoundMatch && d<vBaseWords.size(); d++) {
				String strWord = (String)vBaseWords.get(d);
				String strWhere = new String();
				if(d==0)
					strWhere = new String("Where " + strSourceTable + " Like '" 
						+ strWord.replace("'","''") + " %'");
				else if(d==vBaseWords.size()-1)
					strWhere = new String("Where " + strSourceTable + " Like '% " 
						+ strWord.replace("'","''") + "_'");
				else
					strWhere = new String("Where " + strSourceTable + " Like '% " 
						+ strWord.replace("'","''") + " %'");
						
				ResultSet rsUnusedSentences = DBConnector.select(strStmt + strWhere);
	
				try {
					while(rsUnusedSentences.next() && !bFoundMatch) {
						String strEng = rsUnusedSentences.getString("sentenceEnglish"),
							strFil = rsUnusedSentences.getString("sentenceFilipino"),
							strTokensEng = rsUnusedSentences.getString("tokensEnglish"),
							strTokensFil = rsUnusedSentences.getString("tokensFilipino"),
							strAlignment = rsUnusedSentences.getString("tokenAlignment");
												
						Vector vTokensEng = new Vector(1), vTokensFil = new Vector(1);
						Hashtable htAlignment = new Hashtable();
						
						String[] strTokens;
						int nTokenLength;
						
						strTokens = strTokensEng.split("->");
						nTokenLength = strTokens.length;
						for(int i = 0; i < nTokenLength; i++)
							vTokensEng.add(strTokens[i]);
						String strEnglish = TExtUtility.vecToString(vTokensEng);
						
						strTokens = strTokensFil.split("->");
						nTokenLength = strTokens.length;
						for(int i = 0; i < nTokenLength; i++)
							vTokensFil.add(strTokens[i]);
						String strFilipino = TExtUtility.vecToString(vTokensFil);
						
						TExtSentence tsNewEng = new TExtSentence(vTokensEng, strEnglish),
							tsNewFil = new TExtSentence(vTokensFil, strFilipino);
						
						strTokens = strAlignment.split("->");
						nTokenLength = strTokens.length;
						
						if(bSourceIsFilipino) {
							String strTracker = new String(""), strKey = new String("");
							Vector vKeys = new Vector(), vValues = new Vector();
							for(int i = 0; i < nTokenLength; i++) {
								vKeys.addElement(strTokens[i]);	//eng
								i++;
								vValues.addElement(strTokens[i]);	//fil
							}
		
							Vector vFilTokCopy = (Vector)vTokensFil.clone();
							for(int a=0; a<vFilTokCopy.size(); a++) {
								String strRef = vFilTokCopy.get(a).toString();
								Vector vHashValues = new Vector();
								if(vValues.contains(strRef)) {
									int nOccur = 0;
									while(vValues.contains(strRef)) {
										nOccur++;
										vHashValues.addElement(vKeys.remove(
											vValues.indexOf(strRef)));
										vValues.remove(strRef);
										if(nOccur > 1)
											vFilTokCopy.remove(vFilTokCopy.indexOf(strRef, a+1));
									}
										
									if(htAlignment.containsKey(strRef)){
										vHashValues.addAll(0, (Vector)htAlignment.get(strRef));
										htAlignment.remove(strRef);
									}
									htAlignment.put(strRef,vHashValues);
								} else {
									vFilTokCopy.remove(a);
									a--;
									int nRef;
									do{
										vHashValues.addElement(null);
										nRef = vFilTokCopy.indexOf(strRef, a+1);
										if(nRef != -1)
											vFilTokCopy.remove(nRef);
									}while(nRef != -1);
									if(htAlignment.containsKey(strRef)){
										vHashValues.addAll(0, (Vector)htAlignment.get(strRef));
										htAlignment.remove(strRef);
									}
									htAlignment.put(strRef,vHashValues);
								}
							}
						} else {
							String strTracker = new String(""), strKey = new String("");
							Vector vValues = new Vector();
							for(int i = 0; i < nTokenLength; i++) {
								strKey = strTokens[i];
								System.out.println(strKey);
								if(!strKey.equals(strTracker)) {
									if(vValues.size()>0){
										if(htAlignment.containsKey(strTracker)){
											vValues.addAll(0, (Vector)htAlignment.get(strTracker));
											htAlignment.remove(strTracker);
										}
										htAlignment.put(strTracker, vValues);
									}
									strTracker = strKey;
									vValues = new Vector();
								}
								i++;
								vValues.addElement(strTokens[i]);
							}
							if(!strTracker.equals("")){
								if(htAlignment.containsKey(strTracker)){
									vValues.addAll(0, (Vector)htAlignment.get(strTracker));
									htAlignment.remove(strTracker);
								}
								htAlignment.put(strTracker, vValues);
							}
							// This is for the very last item.
						}

						if(bSourceIsFilipino)
							alMatch = new AlignedSentence(tsNewFil, tsNewEng, htAlignment);
						else
							alMatch = new AlignedSentence(tsNewEng, tsNewFil, htAlignment);
						alMatch.setSourceToFilipino(bSourceIsFilipino);
							
						DBConnector.update("Delete From UnusedSentences Where "
							+ "sentenceEnglish='" + strEng.replace("'","''") + "' And "
							+ "sentenceFilipino='" + strFil.replace("'","''") + "'");
						bFoundMatch = true;
					}
				} catch(SQLException sqle) {
					
					System.err.println("SQL Error: "+sqle.getMessage());
				}
			}
		}
		
		return alMatch;
	}

	/**
	 * Obtains the String matches between two sentences with the token Vector
	 *	parameters.
	 *
	 * @see deriveTemplate(AlignedSentence a, AlignedSentence a)
	 */
	private Vector getStringMatches(Vector vCurrent, Vector vMatch) {
		Vector vMatches = new Vector(1);
		
		boolean hasMatch = false;
		int d = 0;
		for(int a=0; a<vCurrent.size(); a++) {
			String strComp = (String)vCurrent.get(a);
			hasMatch = false;
			for(int b=d; !hasMatch && b<vMatch.size(); b++) {
				String strMatch = (String)vMatch.get(b);
				if(strComp.equalsIgnoreCase(strMatch)) {
					hasMatch = true;
					d = b;
					do {
						a++; d++;
						vMatches.add(strComp);
				
						if(a>=vCurrent.size() || d>=vMatch.size())
							break;
						strComp = (String)vCurrent.get(a);
						strMatch = (String)vMatch.get(d);
					} while(strComp.equalsIgnoreCase(strMatch));
					d++;
				}
			}
		}
		
		return vMatches;
	}	
	
	/**
	 * Constructs the 'STRING'-'CHUNK' pattern between the token Vectors of the
	 *	current and matching sentences.
	 *
	 * @see deriveTemplate(AlignedSentence, AlignedSentence)
	 */
	private Vector constructPattern(Vector vTokens, Vector vSimilarities) {
		Vector vReturn = new Vector(1);
		
		boolean lastWasChunk = false;
		int nMatchPtr = 0, nTempChunkCnt = 0;
		Vector vPattern = new Vector(1);
		for(int f=0; f<vTokens.size(); f++)
			if(nMatchPtr<vSimilarities.size() 
				&& vSimilarities.get(nMatchPtr).toString().equalsIgnoreCase(vTokens.get(f).toString())) {
				//System.out.print("String");
				vPattern.add(new String());
				nMatchPtr++;
				lastWasChunk = false;
			} else {
				if(!lastWasChunk) {
					//System.out.print("Chunk");
					vPattern.add(new TExtChunk());
					nTempChunkCnt++;
				}
				lastWasChunk = true;
			}
		//System.out.println();
		
		vReturn.addElement(vPattern);
		vReturn.addElement(new Integer(nTempChunkCnt));
		
		return vReturn;
	}
	
	/**
	 * Checks whether the tokens, given the similarities, also follow the
	 *	same pattern parameter.
	 *
	 * @see deriveTemplate(AlignedSentence, AlignedSentence)
	 */
	private Vector checkPattern(Vector vTokens, Vector vSimilarities,
		Vector vTemComparison) {
		Vector vReturn = new Vector(1);
		
		int h = 0;
		boolean lastWasChunk = false, bCorrect = true;
		int nMatchPtr = 0, nMatchSChunkCnt = 0;
		Vector vPattern = new Vector(1);
		for(int g=0; g<vTokens.size() && bCorrect; g++)
			if(nMatchPtr<vSimilarities.size() 
				&& vSimilarities.get(nMatchPtr).toString().equalsIgnoreCase(vTokens.get(g).toString())) {
				//System.out.print("String");
				if(lastWasChunk)
					h++;
				if(h == vTemComparison.size()){
					bCorrect = false;
					break;
				}
				if(vTemComparison.get(h) instanceof TExtChunk)
					bCorrect = false;
				nMatchPtr++;
				lastWasChunk = false;
				h++;
			} else {
				if(!lastWasChunk){
					//System.out.print("Chunk");
					nMatchSChunkCnt++;
				}
				if(h == vTemComparison.size()){
					bCorrect = false;
					break;
				}
				if(vTemComparison.get(h) instanceof String)
					bCorrect = false;
				lastWasChunk = true;
			}
		
		vReturn.addElement(new Boolean(bCorrect));
		vReturn.addElement(new Integer(nMatchSChunkCnt));
		
		return vReturn;
	}
	
	/**
	 * gets the strings which should not be included.
	 * input: the [Republic of the Philippines is a] country [in Asia]
	 * return: [the=0 , country=4]
	 * 
	 * @param strPattern something like: the [Republic of the Philippines is a] country [in Asia]
	 * @return a hashtable containing the string (key) index (value)
	 */
	public Hashtable getExcludeList(String strPattern, Vector vTokens){
		Hashtable h = new Hashtable(1);
		String strToken[] = strPattern.split(" ");
		
		boolean bracket = false;
		boolean bAdd = false;;
		int j=0; //iterator for string, i need to skip if token is compound
		for(int i=0; i<vTokens.size(); i++){
			String str = strToken[j];
			bAdd=true;
			if (!bracket && str.charAt(0) == '[') {
				bracket = true;
				bAdd = false;
			}
			
			if (bracket) {
				bAdd=false;
				if (str.charAt(str.length()-1) == ']'){
					bracket = false;
					bAdd=false;
				}
			}
			
			if(bAdd)h.put(vTokens.get(i).toString(), new Integer(i));		
			j+=vTokens.get(i).toString().split(" ").length;
			
		}
		
		
		return h;
	}
	
	
	
	
	
	
	public Hashtable getIncludeList(String strPattern, Vector vTokens, Hashtable hSTTLAlignment){
		
		
		return null;
	}
	
	
	
	
	
	
	
	
	/**
	 * Constructs the template string (StringBuffer version) and builds the 
	 *	corresponding TExtChunk objects.
	 *
	 * @see deriveTemplate(AlignedSentence, AlignedSentence)
	 */
	private Vector constructTemplateStringAndChunks(Vector vTokens,
		Vector vSimilarities, boolean bWithBounds, String strCompID,
		boolean bIsFirstProcedure) {
		Vector vReturn = new Vector(1);
		
		Vector vChunks = new Vector(1), vTempChunk = new Vector(1),
			vRemoved = new Vector(1);
		StringBuffer sbTemp = new StringBuffer();
		String strNextChunk = new String();
		int nChunkTracker, nMatchPtr = 0;
		int nLBound = 0, nUBound, nStart = -1;
		if(bIsFirstProcedure)
			nChunkTracker = 0;
		else
			nChunkTracker = Integer.parseInt(tlu.returnNextChunk());
		boolean lastWasChunk = false;
		
		for(int l=0; l<vTokens.size(); l++){
			if(nMatchPtr<vSimilarities.size() 
				&& vSimilarities.get(nMatchPtr).toString().equalsIgnoreCase(vTokens.get(l).toString())) { 
				if(lastWasChunk) {
					if(bWithBounds)
						vRemoved.add(nStart + "-" + (nLBound-1));
					sbTemp.deleteCharAt(sbTemp.length()-1);
					sbTemp.append("]");
					sbTemp.append(" ");
					TExtChunk cTemp = new TExtChunk();
	//System.out.println(">>>   "+strNextChunk+"   <<<");
					cTemp.setChunk(vTempChunk, "[" + strNextChunk + "]", tlu.makeCompoundIdentifier(vTempChunk));
					vChunks.addElement(cTemp);
				}
				sbTemp.append(vTokens.get(l));
				sbTemp.append(" ");
				nMatchPtr++;
				lastWasChunk = false;
				if(bWithBounds)
					if(vTokens.get(l).toString().contains(" "))
						nLBound += (new StringTokenizer(vTokens.get(l).toString())).countTokens()-1;
			} else {
				if(!lastWasChunk) {
					if(bWithBounds)
						nStart = nLBound;
					vTempChunk = new Vector(1);
					sbTemp.append("[");
					int nNextChunkDomain = nChunkTracker;
					if(bIsFirstProcedure) 
						nNextChunkDomain += Integer.parseInt(tlu.returnNextChunk());
					strNextChunk = "" + nNextChunkDomain;
					nChunkTracker++;
				}
				sbTemp.append(vTokens.get(l));
				sbTemp.append(" ");
				vTempChunk.addElement(vTokens.get(l));
				if(bWithBounds)
					if(!(strCompID.equals("none")) && vTokens.get(l) instanceof String 
						&& vTokens.get(l).toString().contains(" ")){

						nUBound = nLBound + (new StringTokenizer(vTokens.get(l).toString())).countTokens()-1;
						nLBound = nUBound;
					}
				lastWasChunk = true;
			}
			if(bWithBounds)
				nLBound++;
		}
		if(lastWasChunk) {
			vRemoved.add(nStart + "-" + (nLBound-1));
			sbTemp.deleteCharAt(sbTemp.length()-1);
			sbTemp.append("]");
			TExtChunk cTemp = new TExtChunk();
	//System.out.println(">>>   "+strNextChunk+"   <<<");
			cTemp.setChunk(vTempChunk, "[" + strNextChunk + "]", tlu.makeCompoundIdentifier(vTempChunk));
			vChunks.addElement(cTemp);
		}
		
		vReturn.addElement(sbTemp);
		vReturn.addElement(vChunks);
		vReturn.addElement(vRemoved);
		
		return vReturn;
	}

	
	
	
	
	/**
	 * from the similarity match, 
	 * 
	 * if it is not in sttlalignment, add it.
	 * if it is in exclude, add if it is not in sttlalignment
	 * if it is not in exclude, add

	 * @param vMatches the similarity matches
	 * @param vTokens the tokens of the template
	 * @param vExclude exclude list
	 * @param hSTTLAlignment alignment
	 * @return
	 */
	private Vector getDifferenceMatches(Vector vTokens, Hashtable hExclude, Hashtable hSTTLAlignment){
		Vector vDiffMatch = new Vector();
		Hashtable hash2  = (Hashtable)hSTTLAlignment.clone();

		
		for(int i=0; i < vTokens.size(); i++){
			String o =(String) vTokens.get(i);
			boolean x = false;
			Integer nExcludeIndex = (Integer)hExclude.get(o);
				
				//if it is in exclude list, add.
				if (nExcludeIndex != null && i == nExcludeIndex.intValue() ){
					Vector vhashval =(Vector) ((Vector)hash2.get(o)).clone();
					if (vhashval!= null && !vhashval.isEmpty() &&vhashval.get(0) == null) { 
						// i need the hash of include list, temporary lang to
						// if it is not in include list, add
						vDiffMatch.add(o);
						hash2.remove(o);
						continue;
					}else if (vhashval!= null && vhashval.get(0) != null){	
						//((Vector)hash2.get(o)).remove(0); //hash2 talaga to.
						continue;
					}
					else vDiffMatch.add(o);
				}else{
					vDiffMatch.add(o);
				}
		}	
		
		return vDiffMatch;
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	/**
	 * Creates the necessary templates and chunks from the matching unused
	 * sentence found.
	 * //DTS
	 * @param AlignedSentence an aligned sentence to derive a template with
	 * @param AlignedSentence the unused sentence to derive a template with
	 */
	protected boolean deriveTemplate(AlignedSentence alTemp, AlignedSentence alMatch) {
		//System.out.println(",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,");
		TExtSentence senTempS = alTemp.getSource(), senTempT = alTemp.getTarget();
		TExtSentence senMatchS, senMatchT;
		
		boolean bReturnSuccess = false; //v add, returns true of STTL is performed
		
		if(alMatch.isSourceFilipino())
			if(bSourceIsFilipino) {
				senMatchS = alMatch.getSource();
				senMatchT = alMatch.getTarget();
			} else {
				senMatchS = alMatch.getTarget();
				senMatchT = alMatch.getSource();
			}
		else
			if(!bSourceIsFilipino) {
				senMatchS = alMatch.getSource();
				senMatchT = alMatch.getTarget();
			} else {
				senMatchS = alMatch.getTarget();
				senMatchT = alMatch.getSource();
			}
		
		String strTempCompIDS = tlu.makeCompoundIdentifier(senTempS.getWords());
		String strTempCompIDT = tlu.makeCompoundIdentifier(senTempT.getWords());

		Vector vTempTokenS = (Vector)((Vector)senTempS.getWords()).clone(),
			vTempTokenT = (Vector)((Vector)senTempT.getWords()).clone(),
			vMatchTokenS = (Vector)((Vector)senMatchS.getWords()).clone(),
			vMatchTokenT = (Vector)((Vector)senMatchT.getWords()).clone();

		vTempTokenS.remove(vTempTokenS.size()-1);
		vTempTokenT.remove(vTempTokenT.size()-1);
		vMatchTokenS.remove(vMatchTokenS.size()-1);
		vMatchTokenT.remove(vMatchTokenT.size()-1);
		
		Vector vMatchesS = new Vector(1), vMatchesT = new Vector(1);
		 
		Hashtable hSTTLAlignmentS = new Hashtable(1);
		Hashtable hSTTLAlignmentT = new Hashtable(1);
		
		Vector vExcludeS = new Vector(1);
		Vector vExcludeT = new Vector(1);
		
		Hashtable hExcludeS1 = new Hashtable(1);
		Hashtable hExcludeS2 = new Hashtable(1);
		Hashtable hExcludeT1 = new Hashtable(1);
		Hashtable hExcludeT2 = new Hashtable(1);
		
		
		boolean bDTTL = false;

		
		for(int nDTTL=0; nDTTL<2; nDTTL++){
		
			// SOURCE
			vMatchesS = getStringMatches((Vector)vTempTokenS.clone(), 
				(Vector)vMatchTokenS.clone());
			
			Vector vDiffMatchS1 = new Vector(1); //for lunch
			Vector vDiffMatchS2 = new Vector(1); // for dinner

			//testing for differences
			if(bDTTL)
				vDiffMatchS1 = getDifferenceMatches(vTempTokenS, hExcludeS1, hSTTLAlignmentS);		
			else vDiffMatchS1 = vMatchesS;
			
			if(bDTTL) 
				vDiffMatchS2 = getDifferenceMatches(vMatchTokenS, hExcludeS2, hSTTLAlignmentS);
			else vDiffMatchS2 = vMatchesS;
			
			//end testing
			
			System.out.println(vMatchesS);

			//FOR COMMON WORDS
			if(tlu.computeSpecificity(vDiffMatchS1, true) == 0)
				return bReturnSuccess;
			//END FOR COMMON WORDS
		
			//to avoid learning a template with all constants
			if(vTempTokenS.size() == vDiffMatchS1.size() || vDiffMatchS1.size() == 0)
				return bReturnSuccess;
			//end
		
			//System.out.println("Checkpoint 0.5");
			// TARGET
			vMatchesT = getStringMatches((Vector)vTempTokenT.clone(), 
				(Vector)vMatchTokenT.clone());

			Vector vDiffMatchT1 = new Vector(); 
			Vector vDiffMatchT2 = new Vector();
			
			if(bDTTL)
				vDiffMatchT1 = getDifferenceMatches(vTempTokenT, hExcludeT1, hSTTLAlignmentT);
			else vDiffMatchT1 = vMatchesT;
			
			if(bDTTL) 
				vDiffMatchT2 = getDifferenceMatches(vMatchTokenT, hExcludeT2, hSTTLAlignmentT);
			else vDiffMatchT2 = vMatchesT;
			
			
			//System.out.println(vMatchesT);

			//FOR COMMON WORDS
			if(tlu.computeSpecificity(vDiffMatchT1, false) == 0)
				return bReturnSuccess;
			
			if(tlu.computeSpecificity(vDiffMatchT2, false) == 0)
				return bReturnSuccess;
			//END FOR COMMON WORDS

			//to avoid learning a template with all constants
			if(vTempTokenT.size() == vDiffMatchT1.size() || vDiffMatchT1.size() == 0)
				return bReturnSuccess;
			//end
			 
			Vector vResult = new Vector(1);
			// SOURCE
			vResult = constructPattern((Vector)vTempTokenS.clone(), 
				(Vector)vDiffMatchS1.clone());
			Vector vTemplateTempS = (Vector)vResult.get(0);
			int nTempSChunkCnt = ((Integer)vResult.get(1)).intValue();
			
			//System.out.println(".......................");
			
			// TARGET
			vResult = constructPattern((Vector)vTempTokenT.clone(), 
				(Vector)vDiffMatchT1.clone());
			Vector vTemplateTempT = (Vector)vResult.get(0);
			int nTempTChunkCnt = ((Integer)vResult.get(1)).intValue();
			
			
			// SOURCE
			int nMatchSChunkCnt;
			Vector vTemplateTempS2;
			if (bDTTL){
				vResult = constructPattern((Vector)vMatchTokenS.clone(), 
						(Vector)vDiffMatchS2.clone());
				vTemplateTempS2 = (Vector)vResult.get(0);
				nMatchSChunkCnt = ((Integer)vResult.get(1)).intValue();
				
			}else{
				vResult = checkPattern((Vector)vMatchTokenS.clone(),
						(Vector)vDiffMatchS2.clone(), (Vector)vTemplateTempS.clone());
					
				if(!((Boolean)vResult.get(0)).booleanValue() && !bDTTL)
						return bReturnSuccess;
				else
					nMatchSChunkCnt = ((Integer)vResult.get(1)).intValue();
			}

			
			// TARGET
			int nMatchTChunkCnt;
			Vector vTemplateTempT2;
			if(bDTTL){
				vResult = constructPattern((Vector)vMatchTokenT.clone(), 
						(Vector)vDiffMatchT2.clone());
				vTemplateTempT2 = (Vector)vResult.get(0);
				nMatchTChunkCnt = ((Integer)vResult.get(1)).intValue();
				
			}else{
				vResult = checkPattern((Vector)vMatchTokenT.clone(),
						(Vector)vDiffMatchT2.clone(), (Vector)vTemplateTempT.clone());
				if(!((Boolean)vResult.get(0)).booleanValue() && !bDTTL)
					return bReturnSuccess;
				else
					nMatchTChunkCnt = ((Integer)vResult.get(1)).intValue();
			}
			
			
			
			//2nd fail
			if(nTempSChunkCnt != nMatchSChunkCnt || nTempTChunkCnt != nMatchTChunkCnt)
				return bReturnSuccess;

			//FOR VALIDITY OF CONSTANTS		
			if(!tlu.isValidSimilarities((Vector)vDiffMatchS1.clone(), (Vector)vDiffMatchT1.clone(), alTemp.getAlignment()))
				return bReturnSuccess;
			//END FOR VALIDITY OF CONSTANTS


			// SOURCE TEMP lunch here
			//bakit ganun ang nabubuo?!??!?!
			vResult = constructTemplateStringAndChunks((Vector)vTempTokenS.clone(),
				(Vector)vDiffMatchS1.clone(), true, strTempCompIDS, true);
			StringBuffer sbTempS1 = (StringBuffer)vResult.get(0);
			Vector vSourceChunks1 = (Vector)vResult.get(1);
			Vector vRemoved = (Vector)vResult.get(2);
			
			Vector vRemoved2 = tlu.editCompID(strTempCompIDS, vRemoved);
			strTempCompIDS = tlu.adjustCompIDVal(tlu.removeCompID(strTempCompIDS, vRemoved2), vRemoved);
			
		
			// SOURCE MATCH dinner here
			vResult = constructTemplateStringAndChunks((Vector)vMatchTokenS.clone(),
				(Vector)vDiffMatchS2.clone(), false, null, true);
			StringBuffer sbTempS2 = (StringBuffer)vResult.get(0);
			Vector vSourceChunks2 = (Vector)vResult.get(1);
			
			
			// TARGET TEMP
			vResult = constructTemplateStringAndChunks((Vector)vTempTokenT.clone(),
				(Vector)vDiffMatchT1.clone(), true, strTempCompIDT, false);
			StringBuffer sbTempT1 = (StringBuffer)vResult.get(0);
			Vector vTargetChunks1 = (Vector)vResult.get(1);
			vRemoved = (Vector)vResult.get(2);
			
			vRemoved2 = tlu.editCompID(strTempCompIDT, vRemoved);
			strTempCompIDT = tlu.adjustCompIDVal(tlu.removeCompID(strTempCompIDT, vRemoved2), vRemoved);
			
			
			// TARGET MATCH
			vResult = constructTemplateStringAndChunks((Vector)vMatchTokenT.clone(),
				(Vector)vDiffMatchT2.clone(), false, null, false);
			StringBuffer sbTempT2 = (StringBuffer)vResult.get(0);
			Vector vTargetChunks2 = (Vector)vResult.get(1);


	//REPLACE WITH THIS1

			TExtChunkSplitter txtChunkSplit1, txtChunkSplit2;
			txtChunkSplit1 = new TExtChunkSplitter(bSourceIsFilipino, tlu);
			txtChunkSplit2 = new TExtChunkSplitter(bSourceIsFilipino, tlu);
			Vector vChosen1 = null, vChosen2 = null;
			Vector vTempS1 = null, vTempS2 = null;
			Vector vTempT1 = null, vTempT2 = null;
			// failed here
			boolean b11 = txtChunkSplit1.alignChunks(vSourceChunks1, vTargetChunks1, alTemp.getAlignment(), 1);
			boolean b22 = txtChunkSplit2.alignChunks(vSourceChunks2, vTargetChunks2, alMatch.getAlignment(), 2);
			
			
			if(txtChunkSplit1.alignChunks(vSourceChunks1, vTargetChunks1, alTemp.getAlignment(), 1) &&
				txtChunkSplit2.alignChunks(vSourceChunks2, vTargetChunks2, alMatch.getAlignment(), 2)){
				
				Vector vPossRes1 = txtChunkSplit1.getFinalResult(),
					vPossRes2 = txtChunkSplit2.getFinalResult();
			Vector vChosenRes = tlu.chooseAmongAlSplit(vPossRes1, vPossRes2);
				
				if(vChosenRes != null){
					vChosen1 = (Vector)vChosenRes.get(0);
					vChosen2 = (Vector)vChosenRes.get(1);
					
					vSourceChunks1 = (Vector)vChosen1.get(1);
					vTargetChunks1 = (Vector)vChosen1.get(2);
					vTempS1 = (Vector)vChosen1.get(3);
					vTempT1 = (Vector)vChosen1.get(4);
					Vector vDummy1 = tlu.adjustChunkDiv(sbTempS1.toString(), 
						(Vector)vSourceChunks1.clone(), strTempCompIDS);
					Vector vDummy2 = tlu.adjustChunkDiv(sbTempT1.toString(), 
						(Vector)vTargetChunks1.clone(), strTempCompIDT);
					
					if(vDummy1 == null || vDummy2 == null)
						return bReturnSuccess;

					
					if(vDummy1.size() == 2){
						sbTempS1 = (StringBuffer)vDummy1.remove(1);
						strTempCompIDS = new String((String)vDummy1.remove(0));
					}
					else
						sbTempS1 = (StringBuffer)vDummy1.remove(0);
						
					if(vDummy2.size() == 2){
						sbTempT1 = (StringBuffer)vDummy2.remove(1);
						strTempCompIDT = new String((String)vDummy2.remove(0));
					}
					else
						sbTempT1 = (StringBuffer)vDummy2.remove(0);
					
					vSourceChunks2 = (Vector)vChosen2.get(1);
					vTargetChunks2 = (Vector)vChosen2.get(2);
					vTempS2 = (Vector)vChosen2.get(3);
					vTempT2 = (Vector)vChosen2.get(4);
					vDummy1 = tlu.adjustChunkDiv(sbTempS2.toString(), 
						(Vector)vSourceChunks2.clone(), "none");
					vDummy2 = tlu.adjustChunkDiv(sbTempT2.toString(), 
						(Vector)vTargetChunks2.clone(), "none");

					if(vDummy1 == null || vDummy2 == null)
						return bReturnSuccess;

					sbTempS2 = (StringBuffer)vDummy1.remove(0);
					sbTempT2 = (StringBuffer)vDummy2.remove(0);

					vDummy1 = null;
					vDummy2 = null;
				}
				else
					return bReturnSuccess;
			}
			else
				return bReturnSuccess;
	//END REPLACE WITH THIS1

			
	//REPLACE WITH THIS2
			Vector vAlChunkS1 = new Vector(1), vAlChunkT1 = new Vector(1);
			Vector vAlChunkS2 = new Vector(1), vAlChunkT2 = new Vector(1);

			//setdomain
			for(Iterator it = vSourceChunks1.iterator(); it.hasNext(); ){
				TExtChunk outer = (TExtChunk)it.next();
				for(int kCtr = 0; kCtr < vTempS1.size(); kCtr++){
					TExtChunk inner = (TExtChunk)vTempS1.get(kCtr);
					if(outer.equals(inner)){
						vAlChunkS1.add(inner);
						TExtChunk cAlTarget = (TExtChunk)vTempT1.get(kCtr);
						cAlTarget.setDomain(inner.domain());
						vAlChunkT1.add(cAlTarget);
						vTempS1.remove(kCtr);
						vTempT1.remove(kCtr);
						break;
					}
				}
			}

			// setdomain
			for(Iterator it = vSourceChunks2.iterator(); it.hasNext(); ){
				TExtChunk outer = (TExtChunk)it.next();
				for(int kCtr = 0; kCtr < vTempS2.size(); kCtr++){
					TExtChunk inner = (TExtChunk)vTempS2.get(kCtr);
					if(outer.equals(inner)){
						vAlChunkS2.add(inner);
						TExtChunk cAlTarget = (TExtChunk)vTempT2.get(kCtr);
						cAlTarget.setDomain(inner.domain());
						vAlChunkT2.add(cAlTarget);
						vTempS2.remove(kCtr);
						vTempT2.remove(kCtr);
						break;
					}
				}
			}
			
			
	//END REPLACE WITH THIS2
			int nSize = vAlChunkS1.size();
			TExtChunk tempTemp;
			TExtChunk tempInput;
			for(int kCtr = 0; kCtr < nSize; kCtr++){
				tempTemp = (TExtChunk)vAlChunkS1.get(kCtr);
				tempInput = (TExtChunk)vAlChunkS2.get(kCtr);
				tempInput.setDomain(tempTemp.domain());
				vAlChunkS2.setElementAt(tempInput, kCtr);

				tempTemp = (TExtChunk)vAlChunkT1.get(kCtr);
				tempInput = (TExtChunk)vAlChunkT2.get(kCtr);
				tempInput.setDomain(tempTemp.domain());
				vAlChunkT2.setElementAt(tempInput, kCtr);
			}

	//REPLACE WITH THIS
			Hashtable htChunkAlignment1 = new Hashtable();
			Hashtable htChunkAlignment2 = new Hashtable();
			

			htChunkAlignment1.put((Vector)vAlChunkS1.clone(), (Vector)vAlChunkT1.clone());
			htChunkAlignment2.put((Vector)vAlChunkS2.clone(), (Vector)vAlChunkT2.clone());
			
			
	//END REPLACE WITH THIS

			
			
			//to construct the template with the pattern: [I] ate [meat] :to: [1] ate [2]		
			StringBuffer sbTemplateS = new StringBuffer(),
				sbTemplateT = new StringBuffer();
			StringBuffer sbChunk = new StringBuffer();
			String strTempS = sbTempS1.toString(), strTempT = sbTempT1.toString();
			boolean bChunkScan = false;
			for(int p=0; p<strTempS.length(); p++) {
				if(!bChunkScan)
					sbTemplateS.append(strTempS.charAt(p));
				else
					sbChunk.append(strTempS.charAt(p));
				if(strTempS.charAt(p)=='[') {
					sbChunk = new StringBuffer();
					bChunkScan = true;
				} else if(strTempS.charAt(p)==']') {
					sbChunk.deleteCharAt(sbChunk.length()-1);
					for(int q=0; q<vAlChunkS1.size(); q++) {
						TExtChunk cCheck = (TExtChunk)vAlChunkS1.get(q);
						if(cCheck.toString().equals(sbChunk.toString())) {
							sbTemplateS.append(cCheck.domain().substring(1, cCheck.domain().length()-1));
							break;
						}
					}
					sbTemplateS.append(strTempS.charAt(p));
					bChunkScan = false;
				}
			}

			
			sbChunk = new StringBuffer();
			bChunkScan = false;
			for(int r=0; r<strTempT.length(); r++) {
				if(!bChunkScan)
					sbTemplateT.append(strTempT.charAt(r));
				else
					sbChunk.append(strTempT.charAt(r));
				if(strTempT.charAt(r)=='[') {
					sbChunk = new StringBuffer();
					bChunkScan = true;
				} else if(strTempT.charAt(r)==']') {
					sbChunk.deleteCharAt(sbChunk.length()-1);
					for(int s=0; s<vAlChunkT1.size(); s++) {
						TExtChunk cCheck = (TExtChunk)vAlChunkT1.get(s);
						if(cCheck.toString().equals(sbChunk.toString())) {
							sbTemplateT.append(cCheck.domain().substring(1, cCheck.domain().length()-1));
							break;
						}
					}
					sbTemplateT.append(strTempT.charAt(r));
					bChunkScan = false;
				}
			}


			StringBuffer sbTemplateS2 = new StringBuffer(),
				sbTemplateT2 = new StringBuffer();
			StringBuffer sbChunk2 = new StringBuffer();
			String strTempS2 = sbTempS2.toString(), strTempT2 = sbTempT2.toString();
			bChunkScan = false;
			for(int p=0; p<strTempS2.length(); p++) {
				if(!bChunkScan)
					sbTemplateS2.append(strTempS2.charAt(p));
				else
					sbChunk2.append(strTempS2.charAt(p));
				if(strTempS2.charAt(p)=='[') {
					sbChunk2 = new StringBuffer();
					bChunkScan = true;
				} else if(strTempS2.charAt(p)==']') {
					sbChunk2.deleteCharAt(sbChunk2.length()-1);
					for(int q=0; q<vAlChunkS1.size(); q++) {
						TExtChunk cCheck = (TExtChunk)vAlChunkS2.get(q);
						if(cCheck.toString().equals(sbChunk2.toString())) {
							sbTemplateS2.append(cCheck.domain().substring(1, cCheck.domain().length()-1));
							break;
						}
					}
					sbTemplateS2.append(strTempS2.charAt(p));
					bChunkScan = false;
				}
			}

			
			sbChunk2 = new StringBuffer();
			bChunkScan = false;
			for(int r=0; r<strTempT2.length(); r++) {
				if(!bChunkScan)
					sbTemplateT2.append(strTempT2.charAt(r));
				else
					sbChunk2.append(strTempT2.charAt(r));
				if(strTempT2.charAt(r)=='[') {
					sbChunk2 = new StringBuffer();
					bChunkScan = true;
				} else if(strTempT2.charAt(r)==']') {
					sbChunk2.deleteCharAt(sbChunk2.length()-1);
					for(int s=0; s<vAlChunkT2.size(); s++) {
						TExtChunk cCheck = (TExtChunk)vAlChunkT2.get(s);
						if(cCheck.toString().equals(sbChunk2.toString())) {
							sbTemplateT2.append(cCheck.domain().substring(1, cCheck.domain().length()-1));
							break;
						}
					}
					sbTemplateT2.append(strTempT2.charAt(r));
					bChunkScan = false;
				}
			}
				
				TExtTemplate tSource = new TExtTemplate(sbTemplateS.toString(), strTempCompIDS),
					tTarget = new TExtTemplate(sbTemplateT.toString(), strTempCompIDT);
				
				TExtTemplate tSource2 = new TExtTemplate(sbTemplateS2.toString(), strTempCompIDS),
				tTarget2 = new TExtTemplate(sbTemplateT2.toString(), strTempCompIDT); 
							
			/* Update the database with the newly formulated template and chunks.
			 */
			boolean bCheck = true;
			
			if (bDTTL){
				if(bSourceIsFilipino){
					bCheck = updateDatabase(tTarget, tSource, htChunkAlignment1, htChunkAlignment2, false);
					updateDatabase(tTarget2, tSource2, htChunkAlignment1, htChunkAlignment2, false);
				}				  	
				else {
					bCheck = updateDatabase(tSource, tTarget, htChunkAlignment1, htChunkAlignment2, true);
					updateDatabase(tSource2, tTarget2, htChunkAlignment1, htChunkAlignment2, true);
					
				}			 	
			}else{
				if (doSTTL) {
					if(bSourceIsFilipino)				
					  	bCheck = updateDatabase(tTarget, tSource, htChunkAlignment1, htChunkAlignment2, false);
					else 
					 	bCheck = updateDatabase(tSource, tTarget, htChunkAlignment1, htChunkAlignment2, true);
				}
				
				//TODO: hash marker lang
				Vector vs = new Vector(1);
				Vector vt = new Vector(1);
				tSource.adjustTemplateCompound();
				tTarget.adjustTemplateCompound();
				vs.add(tSource);
				vt.add(tTarget);
				hSTTLAlignmentS = getAlignmentInTemplates(vs, vt, bSourceIsFilipino);
				hSTTLAlignmentT = getAlignmentInTemplates(vt, vs, !bSourceIsFilipino);
				
				for(Iterator it = tSource.iterator(); it.hasNext();){
					Object o = it.next();
					if (o instanceof String) vExcludeS.add(o);		
				}
				
				for(Iterator it = tTarget.iterator(); it.hasNext();){
					Object o = it.next();
					if (o instanceof String) vExcludeT.add(o);		
				}
				
				hExcludeS1 = getExcludeList(strTempS, vTempTokenS);
				hExcludeS2 = getExcludeList(strTempS2, vMatchTokenS);
				hExcludeT1 = getExcludeList(strTempT, vTempTokenT);
				hExcludeT2 = getExcludeList(strTempT2, vMatchTokenT);
		
				bReturnSuccess = bCheck;
				
			}
			
			
			
			if(bCheck) {
				Vector vTemp = new Vector(1);
				vTemp.addElement(alTemp);
				vTemp.addElement(alMatch);
				vTemp.addElement(new AlignedTemplate(tSource,tTarget));
				
				Vector vChunks = new Vector(1);
				while(!vAlChunkS1.isEmpty() && !vAlChunkT1.isEmpty())
					vChunks.addElement(new AlignedChunk((TExtChunk)vAlChunkS1.remove(0),
						(TExtChunk)vAlChunkT1.remove(0)));
				while(!vAlChunkS2.isEmpty() && !vAlChunkT2.isEmpty())
					vChunks.addElement(new AlignedChunk((TExtChunk)vAlChunkS2.remove(0),
						(TExtChunk)vAlChunkT2.remove(0)));
				vTemp.addElement(vChunks);
				
				vLearningTracer.addElement(vTemp);
			}
			

			
			if(nDTTL==1 || bDTTL)return bReturnSuccess;
			else{
				bDTTL = true;
			}
			if (!doDTTL) return bReturnSuccess; 
		}
		return false; //v. means did not return bCheck above.
	}
	
	/**
	 * Creates the necessary templates and chunks from the matching chunks
	 * found.
	 *
	 * @param AlignedSentence an aligned sentence to derive a template with
	 * @param Vector chunks matching the aligned sentence
	 */
	protected boolean deriveTemplate(AlignedSentence alTemp, Vector vMatchingChunks) {
		Vector vSourceMatches = new Vector(1), vTargetMatches = new Vector(1);
		Vector vMatchDomains = new Vector(1);
		
		TExtSentence senTempS = alTemp.getSource(), senTempT = alTemp.getTarget();
		Vector vTokenS = (Vector)((Vector)senTempS.getWords()).clone(),
			vTokenT = (Vector)((Vector)senTempT.getWords()).clone();
		
		vTokenS.remove(vTokenS.size()-1);
		vTokenT.remove(vTokenT.size()-1);
				
	//for compound words	
		String strTempSCompID = tlu.makeCompoundIdentifier((Vector)vTokenS.clone());
		String strTempTCompID = tlu.makeCompoundIdentifier((Vector)vTokenT.clone());
	//end

		//System.out.println("Checkpoint O");
		
		/* *KAT* The items here are already chunks.
		 * If we must operate on TExtChunks, just drop '.toString()'
		 */
		for(int a=0; a<vMatchingChunks.size(); a++) {
			if(!vSourceMatches.contains(((AlignedChunk)vMatchingChunks.get(a))
				.getSource())) {
				vSourceMatches.addElement(((AlignedChunk)vMatchingChunks.get(a))
					.getSource());
				vTargetMatches.addElement(((AlignedChunk)vMatchingChunks.get(a))
					.getTarget());
				vMatchDomains.addElement(((AlignedChunk)vMatchingChunks.get(a))
					.getSource().domain());
			}
		}
		/* At this point, there must be an equal amount of corresponding
		 * chunks to use in both the source and target languages.
		 */
		//System.out.println("Checkpoint I");

		/* Finding a matching chunk by subchunk exploration
		 */
		Vector vSData = new Vector(1), vTData = new Vector(1);
		vSData.addAll(vSourceMatches);
		vTData.addAll(vTargetMatches);

		for(int h=0; h<vCPObjects.size(); h++) {
			ChunkPair cpTempS = (ChunkPair)vCPObjects.get(h),
				cpTempT = (ChunkPair)vCPObjects.get(h+1);
	//System.out.print("Iterations "+h);
			h++;
	//System.out.println(" and "+h);
			//System.out.print(cpTempS.getSourceChunk().toString() + " <> ");
			//System.out.println(cpTempT.getTargetChunk().toString() + " of " + cpTempS.getDomain());
			if(!vSData.contains(cpTempS.getSourceChunk())) {
				vSData.addElement(cpTempS.getSourceChunk());
				vTData.addElement(cpTempT.getTargetChunk());
			}// else
				//System.out.println("This entry is a duplicate.");
		}
		
		//System.out.println("Checkpoint II");
	//System.out.println(vSData);
	//System.out.println(vTData);
		
		Vector vSourceTemplates = new Vector(1), vTargetTemplates = new Vector(1);
		Vector vAllDomainsTracker = new Vector(1);
		if(vSData.size()>0 && vTData.size()>0 && vSData.size()==vTData.size()) {
	//System.out.println("SUBCHUNK CHECKING");
			StringBuffer sbSentS = new StringBuffer(),
				sbSentT = new StringBuffer();
			Vector vDupS = new Vector(1), vDupT = new Vector(1);
			for(int j=0; j<vTokenS.size(); j++) {
				sbSentS.append(vTokenS.get(j)).append(' ');
				vDupS.addElement(vTokenS.get(j));
			}
			sbSentS.deleteCharAt(sbSentS.length()-1);
	//System.out.println("curr source sen:"+sbSentS.toString());
			for(int k=0; k<vTokenT.size(); k++) {
				sbSentT.append(vTokenT.get(k)).append(' ');
				vDupT.addElement(vTokenT.get(k));
			}
			sbSentT.deleteCharAt(sbSentT.length()-1);
	//System.out.println("curr target sen:"+sbSentT.toString());
	
			int nBestScore = _nCeilingScoreHeuristic,
				nBestDifference = _nCeilingScoreHeuristic;
			Vector vBestsS = new Vector(1), vBestsT = new Vector(1);

//for compound words
			Vector vBestCIDS = new Vector(1), vBestCIDT = new Vector(1);
//end

			Vector vSTemplatesTemp = new Vector(1), vTTemplatesTemp = new Vector(1);
			Vector vSConflictChunks = new Vector(1), vTConflictChunks = new Vector(1);
			Vector vSAlreadyUsed = new Vector(1), vTAlreadyUsed = new Vector(1);
			Vector vSOverallMonitor = new Vector(1), vTOverallMonitor = new Vector(1);
				
			Vector vSBackup = (Vector)vDupS.clone(), vTBackup = (Vector)vDupT.clone();
			Vector vCSBackup = (Vector)vSData.clone(), vCTBackup = (Vector)vTData.clone();
			String strCompIDSTemp = "none";
			String strCompIDTTemp = "none";
			do {
				//System.out.println("..............................................");
				if(!vSConflictChunks.isEmpty() && !vTConflictChunks.isEmpty()) {
					vSData = (Vector)vCSBackup.clone();
					vTData = (Vector)vCTBackup.clone();
					
					for(int m=0; m<vSConflictChunks.size(); m++)
						vSData.remove(vSConflictChunks.elementAt(m));
					for(int n=0; n<vSConflictChunks.size(); n++)
						vTData.remove(vTConflictChunks.elementAt(n));
					vSData.addAll(0, vSConflictChunks);
					vTData.addAll(0, vTConflictChunks);
					
					vDupS = (Vector)vSBackup.clone();
					vDupT = (Vector)vTBackup.clone();
					
					vSOverallMonitor.addAll(vSConflictChunks);
					vTOverallMonitor.addAll(vTConflictChunks);
				}
				vSConflictChunks.clear();
				vTConflictChunks.clear();
			
				
				//System.out.println("to start");
				//System.out.println(vSData.size()+";"+vTData.size());
				
				// Simultaneous Source-Target Template Construction version
				for(int l=0; l<vSData.size(); l++) {
					Vector vSCurrBackup = (Vector)vDupS.clone(), vTCurrBackup = (Vector)vDupT.clone();
					
		//for compound words	
					strCompIDSTemp = tlu.makeCompoundIdentifier(vDupS);
					strCompIDTTemp = tlu.makeCompoundIdentifier(vDupT);
		//end
	//System.out.println(vSData.get(l).toString());
	//System.out.println(vTData.get(l).toString());
	
	//System.out.println("===== ***** =====");
	//System.out.println(vDupS.toString());
	//System.out.println("===== ***** =====");
	//System.out.println(vDupT.toString());
	//System.out.println("===== ***** =====");
					
					TExtChunk cSource = (TExtChunk)vSData.get(l),
						cTarget = (TExtChunk)vTData.get(l);
					String strDomain = cSource.domain();
					
			//System.out.println("source???"+cSource.toString()+"="+cSource.size()+"="+cSource.getCompoundIdentifier()+"/"+cSource.domain());
			//System.out.println(vDupS);
			//System.out.println("target???"+cTarget.toString()+"="+cTarget.size()+"="+cTarget.getCompoundIdentifier()+"/"+cTarget.domain());
			//System.out.println(vDupT);
			
	//start	for compound words
				//	int nStartIndexS = indexOfChunk(sbSentS, cSource.toString(), 0),
				//		nStartIndexT = indexOfChunk(sbSentT, cTarget.toString(), 0);
					int nStartIndexS = indexOfChunk(vDupS, cSource, 0),
						nStartIndexT = indexOfChunk(vDupT, cTarget, 0);
					Vector vRemovedS = new Vector(1), vRemovedT = new Vector(1);
	// StringTokenizer
				//	int nCSizeTempS = (new StringTokenizer(cSource.toString())).countTokens(),
				//		nCSizeTempT = (new StringTokenizer(cTarget.toString())).countTokens();
					int nCSizeTempS = cSource.size(),
						nCSizeTempT = cTarget.size();
	// end
					//System.out.println("nStartIndexS "+nStartIndexS);
					//System.out.println("nStartIndexT "+nStartIndexT);
					if(nStartIndexS != -1 && nStartIndexT != -1){
					//	vRemovedS.add(nStartIndexS + "-" + (nStartIndexS + nCSizeTempS - 1));
					//	vRemovedT.add(nStartIndexT + "-" + (nStartIndexT + nCSizeTempT - 1));
						int nStartIndexS2 = countPrevTokens(vDupS, nStartIndexS);
						int nStartIndexT2 = countPrevTokens(vDupT, nStartIndexT);
						//System.out.println("nStartIndexS2 "+nStartIndexS2);
						//System.out.println("nStartIndexT2 "+nStartIndexT2);
						vRemovedS.add(nStartIndexS2 + "-" + (nStartIndexS2 + (new StringTokenizer(cSource.toString())).countTokens() - 1));
						vRemovedT.add(nStartIndexT2 + "-" + (nStartIndexT2 + (new StringTokenizer(cTarget.toString())).countTokens() - 1));
					}
					while(nStartIndexS != -1 && nStartIndexT != -1) {
					//	nStartIndexS = indexOfChunk(sbSentS, cSource.toString(), (nStartIndexS + nCSizeTempS));
					//	nStartIndexT = indexOfChunk(sbSentT, cTarget.toString(), (nStartIndexT + nCSizeTempT));
						nStartIndexS = indexOfChunk(vDupS, cSource, (nStartIndexS + nCSizeTempS));
						nStartIndexT = indexOfChunk(vDupT, cTarget, (nStartIndexT + nCSizeTempT));
						//System.out.println("nStartIndexS "+nStartIndexS);
						//System.out.println("nStartIndexT "+nStartIndexT);
						if(nStartIndexS != -1 && nStartIndexT != -1){
						//	vRemovedS.add(nStartIndexS + "-" + (nStartIndexS + nCSizeTempS - 1));
						//	vRemovedT.add(nStartIndexT + "-" + (nStartIndexT + nCSizeTempT - 1));
							int nStartIndexS2 = countPrevTokens(vDupS, nStartIndexS);
							int nStartIndexT2 = countPrevTokens(vDupT, nStartIndexT);
							//System.out.println("nStartIndexS2 "+nStartIndexS2);
							//System.out.println("nStartIndexT2 "+nStartIndexT2);
							vRemovedS.add(nStartIndexS2 + "-" + (nStartIndexS2 + (new StringTokenizer(cSource.toString())).countTokens() - 1));
							vRemovedT.add(nStartIndexT2 + "-" + (nStartIndexT2 + (new StringTokenizer(cTarget.toString())).countTokens() - 1));
						}
					}
					
					//System.out.println(vRemovedS + ";;;" + vRemovedT);
					//System.out.println("()()()()()()()()" + strCompIDSTemp);
					//System.out.println("()()()()()()()()" + strCompIDTTemp);
				//	Vector vRemovedS2 = tlu.editCompID(strTempSCompID, (Vector)vRemovedS.clone()),
				//		vRemovedT2 = tlu.editCompID(strTempTCompID, (Vector)vRemovedT.clone());
					Vector vRemovedS2 = tlu.editCompID(strCompIDSTemp, (Vector)vRemovedS.clone()),
						vRemovedT2 = tlu.editCompID(strCompIDTTemp, (Vector)vRemovedT.clone());
					//System.out.println(vRemovedS2 + ";;;" + vRemovedT2);
				//	strCompIDSTemp = tlu.adjustCompIDVal(tlu.removeCompID(new String(strTempSCompID), (Vector)vRemovedS2.clone()), (Vector)vRemovedS.clone());
				//	strCompIDTTemp = tlu.adjustCompIDVal(tlu.removeCompID(new String(strTempTCompID), (Vector)vRemovedT2.clone()), (Vector)vRemovedT.clone());
					strCompIDSTemp = tlu.adjustCompIDVal(tlu.removeCompID(new String(strCompIDSTemp), (Vector)vRemovedS2.clone()), (Vector)vRemovedS.clone());
					strCompIDTTemp = tlu.adjustCompIDVal(tlu.removeCompID(new String(strCompIDTTemp), (Vector)vRemovedT2.clone()), (Vector)vRemovedT.clone());
				//	String strCompIDSTemp = tlu.adjustCompIDVal(strTempSCompID, (Vector)vRemoved.clone());
	//end for compound words
			
					boolean bRoundSuccess = false;

					int nIndexS = 0, nStartS = -1;
					Vector vChunkS = new Vector(1);
					boolean bCand = false, bDone = false;
					for(int y=0; !bDone && y<vDupS.size(); y++) {
				
				//System.out.print(vDupS.elementAt(y).toString()+" <+> ");
				//System.out.print(cSource.elementAt(nIndexS).toString() + " : ");
				//System.out.println("["+cSource.domain()+"]");
				
						if(vDupS.elementAt(y).toString()
							.equalsIgnoreCase(cSource.elementAt(nIndexS).toString())) {
							if(!bCand) {
								nStartS = y;
								bCand = true;
							}
							nIndexS++;
						} else {
							bCand = false;
							nIndexS = 0;
							nStartS = -1;
						}
						if(nIndexS==cSource.size() && bCand) {
							int nIndexCopy = nIndexS;
							while(nIndexS > 0) {
								vChunkS.addElement(vDupS.remove(nStartS));
								y--;
								nIndexS--;
				//System.out.println(vChunkS.toString());
							}
							Vector vComp = new Vector(1);
							for(int ae=0; ae<vDupS.size(); ae++) {
								if(!vDupS.elementAt(ae).toString().startsWith("[") &&
									!vDupS.elementAt(ae).toString().endsWith("]"))
									vComp.add(vDupS.get(ae));
							}
							if(tlu.computeSpecificity(vComp, true)==0) {
								vDupS.addAll(nStartS, vChunkS);
								nIndexS = 0;
								y += nIndexCopy;
							} else {
								vDupS.insertElementAt("["+strDomain+"]",nStartS);
								bDone = true;								
							}
							nStartS = -1;
							bCand = false;
						}
					}
					if(bDone)
						bRoundSuccess = true;
					//although only half-true; check condition below
					
		//System.out.println(bDone + "< bDone;bRoundSuccess >" + bRoundSuccess);
		//System.out.println(vDupS.toString());
		
					int nIndexT = 0, nStartT = -1;
					Vector vChunkT = new Vector(1);
					bCand = false;
					bDone = false;
					for(int z=0; bRoundSuccess && !bDone && z<vDupT.size(); z++) {
						
				//System.out.print(vDupT.elementAt(z).toString()+" <+> ");
				//System.out.print(cTarget.elementAt(nIndexT).toString() + " : ");
				//System.out.println(cTarget.domain());
						
						if(vDupT.elementAt(z).toString()
							.equalsIgnoreCase(cTarget.elementAt(nIndexT).toString())) {
							if(!bCand) {
								nStartT = z;
								bCand = true;
							}
							nIndexT++;
						} else {
							bCand = false;
							nIndexT = 0;
							nStartT = -1;
						}
						if(nIndexT==cTarget.size() && bCand) {
							int nIndexCopy = nIndexT;
							while(nIndexT > 0) {
								vChunkT.addElement(vDupT.remove(nStartT));
								z--;
								nIndexT--;
				//System.out.println(vChunkT.toString());
							}
							Vector vComp = new Vector(1);
							for(int af=0; af<vDupT.size(); af++) {
								if(!vDupT.elementAt(af).toString().startsWith("[") &&
									!vDupT.elementAt(af).toString().endsWith("]"))
									vComp.add(vDupT.get(af));
							}
							if(tlu.computeSpecificity(vComp, false)==0) {
								vDupT.addAll(nStartT, vChunkT);
								nIndexT = 0;
								z += nIndexCopy;
							} else {
								vDupT.insertElementAt("["+strDomain+"]",nStartT);
								vAllDomainsTracker.addElement(strDomain);
								bDone = true;								
							}
							nStartT = -1;
							bCand = false;
						}
					}
					if(bDone && bRoundSuccess) {
						if(!tlu.isValidSimilarities((Vector)vDupS.clone(), 
							(Vector)vDupT.clone(), alTemp.getAlignment())) {
								vDupS.removeElementAt(nIndexS);
								vDupS.addAll(nIndexS, vChunkS);
								vDupT.removeElementAt(nIndexT);
								vDupT.addAll(nIndexT, vChunkT);
								bDone = false;
							}
					}
					
					if(!bDone && bRoundSuccess) {
						vDupS = (Vector)vSCurrBackup.clone();
						vDupT = (Vector)vTCurrBackup.clone();
						bRoundSuccess = false;
					}
					
		//System.out.println(vDupT.toString());
					/* meaning it was correctly done in the first half but not in
					 * the second half; restore to previous state
					 */
					
					if(!bRoundSuccess) {
						if(!vSAlreadyUsed.contains(cSource.domain()) 
							&& !vTAlreadyUsed.contains(cTarget.domain())) {
							vSConflictChunks.addElement(cSource);
							vTConflictChunks.addElement(cTarget);
						}
					} else {
						if(!vSAlreadyUsed.contains(cSource.domain()))
							vSAlreadyUsed.addElement(cSource.domain());
						if(!vTAlreadyUsed.contains(cTarget.domain()))
							vTAlreadyUsed.addElement(cTarget.domain());
					}
		//System.out.println("conflictchunks:"+vSConflictChunks+";"+vTConflictChunks);
		//System.out.println("alreadyused:"+vSAlreadyUsed+";"+vTAlreadyUsed);
				}
				vSTemplatesTemp.addElement(vDupS);
				vTTemplatesTemp.addElement(vDupT);
				
				int nScoreS = 0, nScoreT = 0;
				StringBuffer sbSTemp = new StringBuffer(), sbTTemp = new StringBuffer();
				
				for(int aa = 0; aa < vDupS.size(); aa++) {
					sbSTemp.append(vDupS.elementAt(aa).toString()).append(' ');
					if(!vDupS.elementAt(aa).toString().contains("[") &&
						!vDupS.elementAt(aa).toString().contains("]"))
						nScoreS++;
				}
				for(int ab = 0; ab < vDupT.size(); ab++) {
					sbTTemp.append(vDupT.elementAt(ab).toString()).append(' ');
					if(!vDupT.elementAt(ab).toString().contains("[") &&
						!vDupT.elementAt(ab).toString().contains("]"))
						nScoreT++;
				}
				
				int nDifference = Math.abs(nScoreS-nScoreT),
					nScore = nScoreS + nScoreT;
				String strSTemp = sbSTemp.toString().trim(),
					strTTemp = sbTTemp.toString().trim();
				if(!vDupS.isEmpty() && !vDupT.isEmpty() && (nScore<nBestScore || 
					(nScore==nBestScore && nDifference<nBestDifference))) {
					nBestScore = nScore;
					nBestDifference = nDifference;
					
					vBestsS.clear();
					vBestsT.clear();
			//for compound words		
					vBestCIDS.clear();
					vBestCIDT.clear();
			//end		
					
					vBestsS.addElement(strSTemp);
					vBestsT.addElement(strTTemp);
			//for compound words
					vBestCIDS.addElement(strCompIDSTemp);
					vBestCIDT.addElement(strCompIDTTemp);
			//end
				} else if(nScore==nBestScore && nDifference==nBestDifference
					&& !vBestsS.contains(strSTemp) && !vBestsT.contains(strTTemp)) {
					vBestsS.addElement(strSTemp);
					vBestsT.addElement(strTTemp);
			//for compound words
					vBestCIDS.addElement(strCompIDSTemp);
					vBestCIDT.addElement(strCompIDTTemp);
			//end
				}
				
			} while(!vSConflictChunks.isEmpty() && !vTConflictChunks.isEmpty()
				&& !vSOverallMonitor.containsAll(vSConflictChunks)
				&& !vTOverallMonitor.containsAll(vTConflictChunks));
			
			//System.out.println("Best template(s) include:");
			for(int ac=0; ac<vBestsS.size(); ac++) {
				if(!vBestsS.get(ac).toString().contains("[") 
					&& !vBestsS.get(ac).toString().contains("]")
					&& !vBestsT.get(ac).toString().contains("[") 
					&& !vBestsT.get(ac).toString().contains("]")) {
					//System.out.println("warning! possible: none.");
					continue;
				}
				//System.out.println(vBestsS.elementAt(ac)+"<->"+vBestsT.elementAt(ac));
				//System.out.println(" has score of "+nBestScore+" and difference of "+nBestDifference);
			}
			
			for(int ad=0; ad<vBestsS.size(); ad++) {
				if(!vBestsS.get(ad).toString().contains("[") 
					&& !vBestsS.get(ad).toString().contains("]")
					&& !vBestsT.get(ad).toString().contains("[") 
					&& !vBestsT.get(ad).toString().contains("]")) 
					continue;
				TExtTemplate tSource = new TExtTemplate(vBestsS.get(ad).toString(), vBestCIDS.get(ad).toString()),
					tTarget = new TExtTemplate(vBestsT.get(ad).toString(), vBestCIDT.get(ad).toString());
	//System.out.println(ad+"_S_'"+tSource.toString()+"' _T_'"+tTarget.toString()+"'");
				vSourceTemplates.addElement(tSource);
				vTargetTemplates.addElement(tTarget);
			// for compound words
				vSourceTemplates.addElement(vBestCIDS.get(ad));
				vTargetTemplates.addElement(vBestCIDT.get(ad));
			// end	
			}	
		}
		
		/* At this point, the template Strings must have been refined further
		 * with the existing chunk(s) that have subchunks.
		 */
		//System.out.println("Checkpoint IV");
						
		if(vSourceTemplates.size() != vTargetTemplates.size() ||
			(vSourceTemplates.size() == 0 &&
			vTargetTemplates.size() == 0))
			return false;

	/*	System.out.println("--->Source<---");
		for(Iterator itTem = vSourceTemplates.iterator(); itTem.hasNext(); )
			System.out.println(itTem.next());
		System.out.println("--->Target<---");
		for(Iterator itTem = vTargetTemplates.iterator(); itTem.hasNext(); )
			System.out.println(itTem.next());
	*/			
		TExtTemplate tSource, tTarget;
		boolean bPassAtLeastOnce = false;
		Vector vTemplates = new Vector(1);
//for compound words, with Kit's edits
		for(int f=0; f<vSourceTemplates.size(); f+=2) {
			if(vSourceTemplates.get(f) instanceof String)
				tSource = new TExtTemplate((String)vSourceTemplates.get(f), (String)vSourceTemplates.get(f+1));
			else
				tSource = (TExtTemplate)vSourceTemplates.get(f);
			if(vTargetTemplates.get(f) instanceof String)
				tTarget = new TExtTemplate((String)vTargetTemplates.get(f), (String)vTargetTemplates.get(f+1));
			else
				tTarget = (TExtTemplate)vTargetTemplates.get(f);
//end
			
			/* Update the database with the newly formulated template and chunks.
			 */
			boolean bCheck = true;
			if(bSourceIsFilipino)
			 	bCheck = updateDatabaseWithTemplates(tTarget, tSource, false);
			else
				bCheck = updateDatabaseWithTemplates(tSource, tTarget, true);
			
			if(bCheck) {
				vTemplates.addElement(new AlignedTemplate(tSource, tTarget));
				bPassAtLeastOnce = true;
			}
		}
		
		Vector vChunks = new Vector(1);
		while(bPassAtLeastOnce && !vAllDomainsTracker.isEmpty()) {
			String strDomRef = vAllDomainsTracker.remove(0).toString();
			
			ResultSet rsChunks = DBConnector.select("SELECT * FROM Chunks WHERE domain LIKE "
				+strDomRef);
			try {
				String strSourceTable = new String(), strTargetTable = new String(),
					strSourceCW = new String(), strTargetCW = new String();
				if(bSourceIsFilipino) {
					strSourceTable = "chunkFilipino";
					strTargetTable = "chunkEnglish";
					strSourceCW = "compIDFilipino";
					strTargetCW = "compIDEnglish";
				}
				else {
					strSourceTable = "chunkEnglish";
					strTargetTable = "chunkFilipino";
					strSourceCW = "compIDEnglish";
					strTargetCW = "compIDFilipino";
				}
				
				while(rsChunks.next()) {
					String strSourceC = rsChunks.getString(strSourceTable),
						strTargetC = rsChunks.getString(strTargetTable),
						strDomainC = rsChunks.getString("domain"),
						strCWSource = rsChunks.getString(strSourceCW),
						strCWTarget = rsChunks.getString(strTargetCW);
					TExtChunk cSource = new TExtChunk(strSourceC, strDomainC, 
						strCWSource), cTarget = new TExtChunk(strTargetC, 
						strDomainC, strCWTarget);
						
			// for compound words
					cSource = tlu.adjustChunkCompound(cSource);
					cTarget = tlu.adjustChunkCompound(cTarget);
			// end
			//System.out.println("^***^cSource: "+cSource);
			//System.out.println("^***^cTarget: "+cTarget);
					vChunks.addElement(new AlignedChunk(cSource, cTarget));
				}
				
			//System.out.println("^***^strDomRef: "+strDomRef);
			} catch(SQLException sqle) {
				System.err.println("SQL Generic Error: "+sqle.getMessage());
			}
		}
		
		if(bPassAtLeastOnce) {
			Vector vTemp = new Vector(1);
			vTemp.addElement(alTemp);
			vTemp.addElement(vTemplates);
			vTemp.addElement(vChunks);
			
			vLearningTracer.addElement(vTemp);
		}
		
		/* At this point, TExtTemplates must have already been formulated from 
		 * the sentence using existing chunk(s).
		 */
		//System.out.println("Checkpoint V");
		
		/*System.out.println("Done with deriving template for a new sentence using"
			+ " existing chunk(s) successful!");
		*/
		return bPassAtLeastOnce;
	}

	protected int indexOfChunk(Vector vWhole, TExtChunk cChunk, int nStartIndex){
		int nIndex = -1;
		Vector vIndices = new Vector(1);
		int nUBound = vWhole.size()-cChunk.size();
		
		for(int i = nStartIndex; i <= nUBound; i++)
			if(((String)vWhole.get(i)).compareToIgnoreCase((String)cChunk.get(0)) == 0)
				vIndices.add(new Integer(i));
		
		for(Iterator it = vIndices.iterator(); it.hasNext() && nIndex == -1; ){
			int nPossStart = ((Integer)it.next()).intValue();
			boolean bMapped = true;
			for(int i = nPossStart+1; i < nPossStart + cChunk.size() && bMapped; i++)
				if(((String)vWhole.get(i)).compareToIgnoreCase((String)cChunk.get(i-nPossStart)) != 0){
					bMapped = false;
					break;
				}
			if(bMapped)
				nIndex = nPossStart;
		}
		return nIndex;
	}
	
	protected int countPrevTokens(Vector vWhole, int nUntilIndex){
		int nCount = 0;
		for(int i = 0; i < nUntilIndex; i++)
			nCount += (new StringTokenizer((String)vWhole.get(i))).countTokens();
		return nCount;	
	}
	
	public boolean hashHasValue(Hashtable h, String s){
		Collection v = (Collection)h.values();
		Enumeration e = h.keys();
		
		while(e!= null && e.hasMoreElements()){
			Object o = e.nextElement();
			Vector v2 = (Vector)h.get(o);
			try{
				if (o != null && v2.get(0).toString().equals(s)) return true;	
			}catch(NullPointerException ee){				
			}catch(Exception eee){}
			
			
		}

		return false;	
	}
	
	public boolean hashHasKey(Hashtable h, String s){
		Enumeration e = h.keys();
		
		for(; e.hasMoreElements(); ) {
			if (e.nextElement().toString().equals(s)) return true;
		}	
		return false;	
	}
	
	
	
	
	

	public String generalizeDomainsDTS(String strCTValue){
		String strCTValue2 = strCTValue;
		String str = strCTValue;
		boolean bProceed = str.contains("[");
		Hashtable hReplacement = new Hashtable();
		Vector vAlreadyAdded = new Vector(1);
		
		while( bProceed){
			int nBegin = str.indexOf('[');
			int nEnd = str.indexOf(']');
			String strDomain = str.substring(nBegin+1, nEnd); // 99/22.1/99.1
			String strNewDomain = new String();
			String arrDomains[] = strDomain.split("/");
			String strCurrentWhole = new String();
			boolean bAddDecimals = true;
			boolean bWholeNumberHasChild = false;
			Vector vCurrentChild = new Vector(1);
			String strChildrenDomains = new String();
			for(int i=0; i < arrDomains.length; i++) {
				
				if(!arrDomains[i].contains(".")){
					strCurrentWhole = arrDomains[i];
				}else{
					vCurrentChild.add(arrDomains[i]);
					if (strChildrenDomains.equals("")){
						strChildrenDomains = arrDomains[i];
					}else{
						strChildrenDomains+="/"+arrDomains[i];
					}
				}
			}//end for
			
			
			
			//search vCurrentChild if any belongs to strCurrentWhole
			for(Iterator it = vCurrentChild.iterator(); it.hasNext();){
				String s = (String)it.next();
				if (TExtUtility.compareBaseDomain(strCurrentWhole, s)){
					bWholeNumberHasChild = true;
					break;
				}
			}
			
			//if yes, add whole, add all child to strNewDomain			
			if (bWholeNumberHasChild){
				strNewDomain = strCurrentWhole +"/"+strChildrenDomains;
			}else{
				strNewDomain = strChildrenDomains;
			}
			
			if (!strNewDomain.equals(""))
			strCTValue2 = strCTValue2.replace(strDomain, strNewDomain);
			
				
			str = str.substring(nEnd+1, str.length());
			bProceed = str.contains("[");
			
		}
		return strCTValue2;
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	/**
	 * Updates the database with the new template and chunk hashtable parameters.
	 *
	 * The first parameter must be English and the other, in Filipino. For the
	 * hashtables, the keys must be in English and the values, in Filipino.
	 *
	 * @param TExtTemplate new template to insert
	 * @param Hashtable new chunks to insert
	 *
	 * @see deriveTemplate(AlignedSentence, AlignedSentence)
	 */
	private boolean updateDatabase(TExtTemplate tEnglish, TExtTemplate tFilipino,
		Hashtable htNewChunks1, Hashtable htNewChunks2, boolean bSourceIsEnglish) {
		

		String strTempE = tEnglish.toString();
		String strTempF = tFilipino.toString();
		boolean isSuccessful = true;
		Vector vBlankFillDomains = new Vector(1);
		Vector vWholeDomainsUsed = new Vector(1);
		Hashtable hOldNewDomainMap = new Hashtable();
		DBConnector.setAutoCommit(false);
				
		String strSource = new String(), strTarget = new String();
		if(bSourceIsEnglish) {
			strSource = "English";
			strTarget = "Filipino";
		} else {
			strSource = "Filipino";
			strTarget = "English";			
		}
		try {
			Vector vAlternatives = new Vector(1);
			if(htNewChunks1 != null && htNewChunks2 != null) {
			
				// RESOLVE START
				Vector vKeys = new Vector(1), vElements = new Vector(1), vTemp;
				vKeys.addAll((Vector)htNewChunks1.keys().nextElement());
				vElements.addAll((Vector)htNewChunks1.elements().nextElement());
				vKeys.addAll((Vector)htNewChunks2.keys().nextElement());
				vElements.addAll((Vector)htNewChunks2.elements().nextElement());
				// RESOLVE END
				
				String strInsertOrder = new String();
				if(bSourceIsEnglish)
					strInsertOrder = "chunkEnglish, chunkFilipino";
				else
					strInsertOrder = "chunkFilipino, chunkEnglish";
				
				for(int b=0; isSuccessful && b<vKeys.size(); b++) {
					TExtChunk cSourceChunk = (TExtChunk)vKeys.get(b);
					String strSDomTemp = cSourceChunk.domain();
					if(strSDomTemp.startsWith("[") && strSDomTemp.endsWith("]"))
						cSourceChunk.setDomain(strSDomTemp.substring(1, strSDomTemp.length()-1));
					
					TExtChunk cCurrTarget = (TExtChunk)vElements.get(b);
					String strTDomTemp = cCurrTarget.domain();
					if(strTDomTemp.startsWith("[") && strTDomTemp.endsWith("]"))
						cCurrTarget.setDomain(strTDomTemp.substring(1, strTDomTemp.length()-1));
					String strDomain = cCurrTarget.domain();

					String strDomExtS = new String(""), strDomExtT = new String("");
					if(!cSourceChunk.domain().contains("."))
						strDomExtS = new String(".");
					if(!strDomain.contains("."))
						strDomExtT = new String(".");

					
					String strCWEng;
					String strCWFil;
					if(bSourceIsEnglish){
						strCWFil = cCurrTarget.getCompoundIdentifier();
						strCWEng = cSourceChunk.getCompoundIdentifier();
					}
					else{
						strCWEng = cCurrTarget.getCompoundIdentifier();
						strCWFil = cSourceChunk.getCompoundIdentifier();
					}

					if(strCWEng==null)
						strCWEng = new String("none");
					if(strCWFil==null)
						strCWFil = new String("none");
					
					boolean bToUpdateBlank = false;
					ResultSet rsTemp = DBConnector.select("Select * From Chunks"
						+ " Where chunk" + strSource + "='"
						+ cSourceChunk.toString().replace("'","''") 
						+ "' And chunk" + strTarget + "='"
						+ cCurrTarget.toString().replace("'","''")
						+ "' And compIDEnglish='" + strCWEng 
						+ "' And compIDFilipino='" + strCWFil + "'");

					
					if(strDomain.contains(".")) {
						int nIndex = strDomain.indexOf('.');
						strDomain = strDomain.substring(0,nIndex);
					}
					
					ResultSet rsDom = DBConnector.select("Select * From Chunks "
						+ "Where domain Like '" + strDomain + ".%'");
					
					if(rsDom.next()) {
						double dMax = 0.0;
						do {
							double dTemp = rsDom.getDouble("domain");
							if(dTemp>dMax)
								dMax = dTemp;
						} while(rsDom.next());
							StringTokenizer stTemp = new 
								StringTokenizer(""+dMax,".");
							String strGarbage = stTemp.nextToken();
							strDomain = strDomain+"."
								+(Integer.parseInt(stTemp.nextToken())+1);

					} else {
						strDomain = strDomain+".1";
						if(vBlankFillDomains.contains(strDomain))
							bToUpdateBlank = true;
					}
					
					
					
					
					// if chunk has no duplicate in the chunkEnglish/Fil part
					if(!rsTemp.next()) {
						String strInsertOrder2;
						
						if(bSourceIsEnglish)
							strInsertOrder2 = " constCntEng, constCntFil";
						else
							strInsertOrder2 = " constCntFil, constCntEng";
							
						int nCnstCntS = 0, nCnstCntT = 0;
						
						for(Iterator it = cSourceChunk.iterator(); it.hasNext(); )
							if(it.next() instanceof String)
								nCnstCntS++;
						for(Iterator it = cCurrTarget.iterator(); it.hasNext(); )
							if(it.next() instanceof String)
								nCnstCntT++;
						
						if(bToUpdateBlank) 
							vBlankFillDomains.remove(strDomain);

						
						

						//V call recurssion start
						
						TExtChunk cS = cSourceChunk;
						cS.setDomain(strDomain);
						TExtChunk cT = cCurrTarget;
						cT.setDomain(strDomain);
						hOldNewDomainMap = new Hashtable();
						
						boolean bRefinementDone = false; 
						if (TExtLearner.doChunkRefinement)
							bRefinementDone= cr.chunkRefinement(new AlignedChunk(cS, cT), null, null, hOldNewDomainMap);
					
						//V call recurssion end
						
						
						if (!bRefinementDone){
							isSuccessful = DBConnector.update("Insert Into Chunks"
									+ " (" + strInsertOrder + ", domain,"
									+ " compIDEnglish, compIDFilipino," + strInsertOrder2
									+ ") Values ('" + cSourceChunk.toString().replace("'","''")
									+ "','"	+ cCurrTarget.toString().replace("'","''")
									+ "','" + strDomain + "','" + strCWEng
									+ "','" + strCWFil + "'," + nCnstCntS + "," + nCnstCntT + ")");
							
							//add the domains
							strTempE = strTempE.replace("["+stripSquareBrackets(strSDomTemp)+"]",  "["+stripSquareBrackets(strSDomTemp)+"/"+strDomain+"]");
							strTempF = strTempF.replace("["+stripSquareBrackets(strSDomTemp)+"]",  "["+stripSquareBrackets(strSDomTemp)+"/"+strDomain+"]");
							vWholeDomainsUsed.add(cSourceChunk.domain());			
							
						}else{

							/* if refinement was done, the domain of the product chunk changed
							 * because it's original form was deleted because of generalization.
							 * MOD PARENT HERE. 
							 * 
							 */
							
							
							/*TODO: 94.1 should be 93.3, but in template is 94.
							 * if the chunkDB contains many 94s eg 94.1 94.2, retain 94, add the new domain
							 * if the chunkDB has no 94, replace it with the new domain.
							 */
							//replace ASAP if it is not whole
							if(TExtUtility.compareBaseDomain(stripSquareBrackets(strSDomTemp), (String)hOldNewDomainMap.get(strDomain))){
								vWholeDomainsUsed.add(stripSquareBrackets(strSDomTemp));
								strTempE = strTempE.replace("["+stripSquareBrackets(strSDomTemp)+"]",  "["+stripSquareBrackets(strSDomTemp)+"/"+strDomain+"]");
								strTempF = strTempF.replace("["+stripSquareBrackets(strSDomTemp)+"]",  "["+stripSquareBrackets(strSDomTemp)+"/"+strDomain+"]");
							}
							
							
							if(strSDomTemp.contains(".")){
								//strDomain replace? or strSDomTemp?
								//this will replace exact duplicate
								strTempE = strTempE.replace("["+strDomain+"]","["+(String)hOldNewDomainMap.get(strDomain) +"]");
								strTempF = strTempF.replace("["+strDomain+"]","["+(String)hOldNewDomainMap.get(strDomain) +"]");
								//the replacement was not added
								
								String strWholeVar = strDomain.substring(0, strDomain.indexOf('.'));
								strTempE = strTempE.replace("["+strWholeVar+"]","["+strWholeVar+"/"+(String)hOldNewDomainMap.get(strDomain) +"]");
								strTempF = strTempF.replace("["+strWholeVar+"]","["+strWholeVar+"/"+(String)hOldNewDomainMap.get(strDomain) +"]");

								
							}else{
								//i need to add it,, does this even happen? yes
								String strWholeVar = strDomain.substring(0, strDomain.indexOf('.'));
								strTempE = strTempE.replace("["+strWholeVar+"]","["+strWholeVar+"/"+(String)hOldNewDomainMap.get(strDomain) +"]");
								strTempF = strTempF.replace("["+strWholeVar+"]","["+strWholeVar+"/"+(String)hOldNewDomainMap.get(strDomain) +"]");
							}
												
						}


					} else {
						
						String strDupDomain = rsTemp.getString("domain");
						
						/* 
						 * This part is highly modified... danger? yes 
						 */
						
						//should only be used by DTTL
						boolean bDupIsSimilar = true;
						if (strDupDomain.contains("."))
						 bDupIsSimilar = strDupDomain.substring(0, strDupDomain.indexOf(".")).equals(cSourceChunk.domain());
				
						if(!bDupIsSimilar)	{
							vAlternatives.addElement(cSourceChunk.domain());
							vAlternatives.addElement(strDupDomain);
							//when do i call these?
						}else{
							//if the duplicate is a child of the whole domain, add it.
							String strWholeVar = strDomain.substring(0, strDomain.indexOf('.'));
							strTempE = strTempE.replace("["+strWholeVar+"]","["+strWholeVar+"/"+ strDupDomain+"]");
							strTempF = strTempF.replace("["+strWholeVar+"]","["+strWholeVar+"/"+strDupDomain +"]");
						}
						
						
						
					}
				}
				

				
				while(!vBlankFillDomains.isEmpty()) {
					JOptionPane.showMessageDialog(null, vBlankFillDomains);
					String strDomFill = vBlankFillDomains.remove(0).toString();
					/*
					isSuccessful = DBConnector.update("Insert Into Chunks"
						+ " (" + strInsertOrder + ", domain) Values ('','','" 
						+ strDomFill + "')");
					*/
				}
			}
			
			if((tEnglish != null) && (tFilipino != null) && isSuccessful) {
				String strTemplE = strTempE, strTemplF = strTempF;
				
				for(int a=0; a<vAlternatives.size(); a+=2) {
					strTemplE = strTemplE.replace("["+vAlternatives.get(a)+"/",
						"["+vAlternatives.get(a)+"/"+vAlternatives.get(a+1)+"/");
					strTemplF = strTemplF.replace("["+vAlternatives.get(a)+"/",
						"["+vAlternatives.get(a)+"/"+vAlternatives.get(a+1)+"/");
					strTemplE = strTemplE.replace("["+vAlternatives.get(a)+"]",
						"["+vAlternatives.get(a)+"/"+vAlternatives.get(a+1)+"]");
					strTemplF = strTemplF.replace("["+vAlternatives.get(a)+"]",
						"["+vAlternatives.get(a)+"/"+vAlternatives.get(a+1)+"]");
				}
				
				//generalize domains here
				// remove the whole domains which are not in this list domain(vector domains used)
				
	//			strTemplE = removeWholeDomainsNotInThisList(strTemplE, vWholeDomainsUsed);
	//			strTemplF = removeWholeDomainsNotInThisList(strTemplF, vWholeDomainsUsed);

				strTemplE = generalizeDomainsDTS(strTemplE);
				strTemplF = generalizeDomainsDTS(strTemplF);
				
				strTemplE = tlu.generalizeDomains(strTemplE);
				strTemplF = tlu.generalizeDomains(strTemplF);
				
				String strCWEng = tEnglish.getCompoundIdentifier(),
					strCWFil = tFilipino.getCompoundIdentifier();
				ResultSet rsTemp = DBConnector.select("Select * From Templates Where"
					+ " templateEnglish='" + strTemplE.replace("'","''")
					+ "' And templateFilipino='" 
					+ strTemplF.replace("'","''") 
					+ "' And compIDEnglish='" + strCWEng + "' And compIDFilipino='" 
					+ strCWFil + "'");
					
				if(!rsTemp.next()) {					
					int nCnstCntE = 0, nCnstCntF = 0;
					
					for(Iterator it = tEnglish.iterator(); it.hasNext(); )
						if(it.next() instanceof String)
							nCnstCntE++;
					for(Iterator it = tFilipino.iterator(); it.hasNext(); )
						if(it.next() instanceof String)
							nCnstCntF++;
								
					isSuccessful = DBConnector.update("Insert Into Templates"
						+ " (templateEnglish, templateFilipino, compIDEnglish,"
						+ " compIDFilipino, constCntEng, constCntFil) Values ('" 
						+ strTemplE.replace("'","''") + "','" 
						+ strTemplF.replace("'","''") + "','" 
						+ strCWEng + "','" + strCWFil + "'," + nCnstCntE
						+ "," + nCnstCntF + ")");
				}
				
				rsTemp.close();
			}
			
			if(!isSuccessful)
				DBConnector.rollback();
			else
				DBConnector.commit();
		} catch(SQLException sqle) {
			System.out.println("Generic update error: "+sqle.getMessage());
			DBConnector.rollback();
			
			
			
		}
		
		DBConnector.setAutoCommit(true);
		
		return isSuccessful;
	}	
	
	
	
	protected String stripSquareBrackets(String strDomain) {
		
		if(strDomain != null && strDomain.startsWith("[") && strDomain.endsWith("]")) {
			//strip the [] off
			strDomain = strDomain.substring(1, strDomain.length() - 1);
		}
		
		return strDomain;
	}

	
	
	
	
	
	
	public String removeWholeDomainsNotInThisList(String strCTValue, Vector vInclude){


		String strCTValue2 = strCTValue;
		String str = strCTValue;
		boolean bProceed = str.contains("[");

		while( bProceed) {
			int nBegin = str.indexOf('[');
			int nEnd = str.indexOf(']');
			String strDomain = str.substring(nBegin+1, nEnd); // 99/22.1/99.1
			String strNewDomain = new String();
			String arrDomains[] = strDomain.split("/");
			String strCurrentWhole = new String();
			boolean bAddDecimals = true;
			for(int i=0; i < arrDomains.length; i++) {

				if (!arrDomains[i].contains(".")) {
					strCurrentWhole = arrDomains[i];

					if (vInclude.contains(strCurrentWhole)){
						if(strNewDomain.equals("")){
							strNewDomain+=strCurrentWhole;
						}else{
							strNewDomain+="/"+strCurrentWhole;
						}						
					}
				}else{
						if(strNewDomain.equals("")){
							strNewDomain+=arrDomains[i];
						}else{
							strNewDomain+="/"+arrDomains[i];
						}			
				}//endif
			}//end for
			
			strCTValue2 = strCTValue2.replace(strDomain, strNewDomain);
				
			str = str.substring(nEnd+1, str.length());
			bProceed = str.contains("[");
		
		}//end while
		
		return strCTValue2;
		
	}//end func
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	/**
	 * Updates the database with the new templates in the parameters.
	 *
	 * The first parameter must be English and the other, in Filipino.
	 *
	 * @param TExtTemplate new template to insert
	 * @param boolean whether the source in this case is in English
	 *
	 * @see deriveTemplate(AlignedSentence, Vector)
	 */
	private boolean updateDatabaseWithTemplates(TExtTemplate tEnglish, 
		TExtTemplate tFilipino, boolean bSourceIsEnglish) {
		
	//	JOptionPane.showMessageDialog(null, "DTFC");
	//	JOptionPane.showMessageDialog(null, "tEnglish-->" + tEnglish);
	//	JOptionPane.showMessageDialog(null, "tFilipino-->" + tFilipino);
		
		boolean isSuccessful = true;
			
		DBConnector.setAutoCommit(false);
		
		try {			
			if((tEnglish != null) && (tFilipino != null)) {
				//System.out.println("Update the template database.");
				String strTemplE = tEnglish.toString(), strTemplF = tFilipino.toString();
				
				String strCWEng = tEnglish.getCompoundIdentifier(),
					strCWFil = tFilipino.getCompoundIdentifier();
				ResultSet rsTemp = DBConnector.select("Select * From Templates Where"
					+ " templateEnglish='" + strTemplE.replace("'","''")
					+ "' And templateFilipino='" + strTemplF.replace("'","''") 
					+ "' And compIDEnglish='" + strCWEng 
					+ "' And compIDFilipino='" + strCWFil + "'");
				
				if(!rsTemp.next()) {					
					int nCnstCntE = 0, nCnstCntF = 0;
					
					for(Iterator it = tEnglish.iterator(); it.hasNext(); )
						if(it.next() instanceof String)
							nCnstCntE++;
					for(Iterator it = tFilipino.iterator(); it.hasNext(); )
						if(it.next() instanceof String)
							nCnstCntF++;
								
					isSuccessful = DBConnector.update("Insert Into Templates"
						+ " (templateEnglish, templateFilipino, compIDEnglish,"
						+ " compIDFilipino, constCntEng, constCntFil) Values ('" 
						+ strTemplE.replace("'","''") + "','" 
						+ strTemplF.replace("'","''") + "','" 
						+ strCWEng + "','" + strCWFil + "'," + nCnstCntE
						+ "," + nCnstCntF + ")");
					
				} //else
					//System.out.println("There is a duplicate template.");
					//check dito if same yun strCompIDField nila.  if no, insert.
			}
			
			if(!isSuccessful)
				DBConnector.rollback();
			else
				DBConnector.commit();
		} catch(SQLException sqle) {
			System.out.println("Generic update error: "+sqle.getMessage());
			DBConnector.rollback();
		}
		
		DBConnector.setAutoCommit(true);
		
		return isSuccessful;
	}
	
	/* Sends all the unused sentences for learning to the database.
	 *
	 * @see learnTemplate(Vector)
	 */
	private void storeUnusedSentences() {
		if(vUnmatchedSentences.size()==0)
			return;
			
		try {	
			//System.out.println("Update the unused sentence database.");
			for(int a=0; a<vUnmatchedSentences.size(); a++) {
				StringBuffer sbTokensEng = new StringBuffer(), 
					sbTokensFil = new StringBuffer();
				
				Iterator itEng;
				Iterator itFil;
				
				Vector vEngTokClone;
				
				if(bSourceIsFilipino) {
					itFil = ((AlignedSentence)vUnmatchedSentences.get(a)).getSource().getWords().iterator();
					itEng = ((AlignedSentence)vUnmatchedSentences.get(a)).getTarget().getWords().iterator();
					vEngTokClone = ((AlignedSentence)vUnmatchedSentences.get(a)).getTarget().getWords();
				} else {
					itEng = ((AlignedSentence)vUnmatchedSentences.get(a)).getSource().getWords().iterator();
					itFil = ((AlignedSentence)vUnmatchedSentences.get(a)).getTarget().getWords().iterator();
					vEngTokClone = new Vector(1);
				}
				
				while(itEng.hasNext()){
					sbTokensEng.append((String)itEng.next());
					if(itEng.hasNext())
						sbTokensEng.append("->");
				}
				while(itFil.hasNext()){
					sbTokensFil.append((String)itFil.next());
					if(itFil.hasNext())
						sbTokensFil.append("->");
				}
				
				StringBuffer sbAlignment = new StringBuffer();
				Hashtable htAlign = ((AlignedSentence)vUnmatchedSentences.get(a)).getAlignment();
				
				Enumeration enumKeys = htAlign.keys();
				
				boolean bHasAdded;
				while(enumKeys.hasMoreElements()) {
					String strKey = enumKeys.nextElement().toString();
					Vector vValues = (Vector)htAlign.get(strKey);
					
					bHasAdded = false;
					for(Iterator it = vValues.iterator(); it.hasNext(); ) {
						Object oValue = it.next();
						if(bSourceIsFilipino && oValue != null){
							bHasAdded = true;
							sbAlignment.append(oValue + "->" + strKey);
							vEngTokClone.remove(oValue);
							if(it.hasNext()){
								sbAlignment.append("->");
							}
						}
						else if(bSourceIsFilipino && oValue == null && bHasAdded){
							sbAlignment = sbAlignment.replace(sbAlignment.length()-2, sbAlignment.length(), "");
						}
						else if(!bSourceIsFilipino){
							bHasAdded = true;
							sbAlignment.append(strKey + "->" + oValue);
							if(it.hasNext())
								sbAlignment.append("->");
						}
					}
					if(bHasAdded && enumKeys.hasMoreElements()){
						sbAlignment.append("->");
					}
				}
				if(bSourceIsFilipino && vEngTokClone.size() > 0){
					String strAlignVer = sbAlignment.toString();
					while(strAlignVer.endsWith("->")){
						strAlignVer = strAlignVer.substring(0, strAlignVer.length()-2);
						sbAlignment = new StringBuffer(strAlignVer);
					}
					String strRem;
					for(int i = 0; i < vEngTokClone.size(); i++){
						strRem = (String)vEngTokClone.remove(i);
						i--;
						int nRem;
						do{
							sbAlignment.append("->" + strRem + "->" + null);
							nRem = vEngTokClone.indexOf(strRem);
							if(nRem != -1)
								vEngTokClone.remove(nRem);
						}while(nRem != -1);
					}
				}
				
				String strSentS = ((AlignedSentence)vUnmatchedSentences.get(a))
					.getSource().toString(),
					strSentT = ((AlignedSentence)vUnmatchedSentences.get(a))
					.getTarget().toString();
				String strSenEng = new String(), strSenFil = new String();
				if(bSourceIsFilipino) {
					strSenEng = strSentT;
					strSenFil = strSentS;
				} else {
					strSenEng = strSentS;
					strSenFil = strSentT;
				}
				
				ResultSet rsTemp = DBConnector.select("Select * From UnusedSentences Where"
					+ " sentenceEnglish='" + strSenEng.replace("'","''")
					+ "' And sentenceFilipino='" + strSenFil.replace("'","''")
					+ "' And tokensEnglish='" + sbTokensEng.toString().replace("'","''")
					+ "' And tokensFilipino='" + sbTokensFil.toString().replace("'","''")
					+ "'");

				if(!rsTemp.next())
					DBConnector.update("Insert Into UnusedSentences (sentenceEnglish,"
						+ " sentenceFilipino, tokensEnglish, tokensFilipino, tokenAlignment)"
						+ " Values ('" + strSenEng.replace("'","''") + "','"
						+ strSenFil.replace("'","''") + "','"
						+ sbTokensEng.toString().replace("'","''") + "','"
						+ sbTokensFil.toString().replace("'","''") + "','"
						+ sbAlignment.toString().replace("'","''") + "')");
			}
		} catch(SQLException sqle) {
			System.out.println("Generic update error: "+sqle.getMessage());
		}
		
		System.out.println("Successfully stored unused sentences.");
		vUnmatchedSentences.clear();
	}

	/* Loads all the unused sentences for learning from the database.
	 *
	 * @see learnTemplate(Vector)
	 *
	 * @deprecated as of 1.01.08
	 */
	private void loadUnusedSentences() {
		String strQuery = "Select * From UnusedSentences";
		try {
			ResultSet rsTemp = DBConnector.select(strQuery);
			while(rsTemp.next()) {
		//		System.out.println("=========================================");
				String strTokensEng = rsTemp.getString("tokensEnglish"),
					strTokensFil = rsTemp.getString("tokensFilipino"),
					strAlignment = rsTemp.getString("tokenAlignment");

				DBConnector.update("DELETE FROM UnusedSentences WHERE tokensEnglish = '" + strTokensEng + "' And tokensFilipino = '" + strTokensFil + "'");
				
				Vector vTokensEng = new Vector(1);
				Vector vTokensFil = new Vector(1);
				Hashtable htAlignment = new Hashtable();
				
				String[] strTokens;
				int nTokenLength;
				
				strTokens = strTokensEng.split("->");
				nTokenLength = strTokens.length;
				for(int i = 0; i < nTokenLength; i++)
					vTokensEng.add(strTokens[i]);
				String strEnglish = TExtUtility.vecToString(vTokensEng);
				
				strTokens = strTokensFil.split("->");
				nTokenLength = strTokens.length;
				for(int i = 0; i < nTokenLength; i++)
					vTokensFil.add(strTokens[i]);
				String strFilipino = TExtUtility.vecToString(vTokensFil);
				
				TExtSentence tsNewEng = new TExtSentence(vTokensEng, strEnglish),
					tsNewFil = new TExtSentence(vTokensFil, strFilipino);
				
				strTokens = strAlignment.split("->");
				nTokenLength = strTokens.length;
				
				if(bSourceIsFilipino) {
					String strTracker = new String(""), strKey = new String("");
					Vector vKeys = new Vector(1), vValues = new Vector(1);
					for(int i = 0; i < nTokenLength; i++) {
						vKeys.addElement(strTokens[i]);	//eng
						i++;
						vValues.addElement(strTokens[i]);	//fil
					}
					Vector vFilTokCopy = (Vector)vTokensFil.clone();
					for(int a=0; a<vFilTokCopy.size(); a++) {
						String strRef = vFilTokCopy.get(a).toString();
						Vector vHashValues = new Vector(1);
						if(vValues.contains(strRef)) {
							int nOccur = 0;
							while(vValues.contains(strRef)) {
								nOccur++;
								vHashValues.addElement(vKeys.remove(
									vValues.indexOf(strRef)));
								vValues.remove(strRef);
								if(nOccur > 1)
									vFilTokCopy.remove(vFilTokCopy.indexOf(strRef, a+1));
							}
								
							if(htAlignment.containsKey(strRef)){
								vHashValues.addAll(0, (Vector)htAlignment.get(strRef));
								htAlignment.remove(strRef);
							}
							htAlignment.put(strRef,vHashValues);
						} else {
							vFilTokCopy.remove(a);
							a--;
							int nRef;
							do{
								vHashValues.addElement(null);
								nRef = vFilTokCopy.indexOf(strRef, a+1);
								if(nRef != -1)
									vFilTokCopy.remove(nRef);
							}while(nRef != -1);
							if(htAlignment.containsKey(strRef)){
								vHashValues.addAll(0, (Vector)htAlignment.get(strRef));
								htAlignment.remove(strRef);
							}
							htAlignment.put(strRef,vHashValues);
						}
					}
				} else {
					String strTracker = new String(""), strKey = new String("");
					Vector vValues = new Vector(1);
					for(int i = 0; i < nTokenLength; i++) {
						strKey = strTokens[i];
						//System.out.println(strKey);
						if(!strKey.equals(strTracker)) {
							if(vValues.size()>0){
								if(htAlignment.containsKey(strTracker)){
									vValues.addAll(0, (Vector)htAlignment.get(strTracker));
									htAlignment.remove(strTracker);
								}
								htAlignment.put(strTracker, vValues);
							}
							strTracker = strKey;
							vValues = new Vector(1);
						}
						i++;
						vValues.addElement(strTokens[i]);
					}
					if(!strTracker.equals("")){
						if(htAlignment.containsKey(strTracker)){
							vValues.addAll(0, (Vector)htAlignment.get(strTracker));
							htAlignment.remove(strTracker);
						}
						htAlignment.put(strTracker, vValues);
					}
					// This is for the very last item.
				}
				if(bSourceIsFilipino){
					AlignedSentence alSen = new AlignedSentence(tsNewFil, tsNewEng, htAlignment);
					alSen.setSourceToFilipino(bSourceIsFilipino);
					vUnmatchedSentences.addElement(alSen);
				}
				else{
					AlignedSentence alSen = new AlignedSentence(tsNewEng, tsNewFil, htAlignment);
					alSen.setSourceToFilipino(bSourceIsFilipino);
					vUnmatchedSentences.addElement(alSen);
				}
			}
		} catch(SQLException sqle) {
			System.out.println("Generic select error: "+sqle.getMessage());
		}
		//System.out.println("Successfully loaded unused sentences.");
	}
	
	/* Sends all the unused sentences for learning to an external text file.
	 *
	 * @see learnTemplate(Vector)
	 *
	 * @deprecated as of 1.01.05
	 */
	// GOOD
	private void flushUnusedSentences() {
		try {
			java.io.File outputFile1, outputFile2;
			int index=0;
			do {
				String prefix = "";
				if(index<10)
					prefix += "0";
				outputFile1 = new 
					java.io.File("logs/UnusedSourceSentences_"+prefix+index+".txt");
				outputFile2 = new 
					java.io.File("logs/UnusedTargetSentences_"+prefix+index+".txt");
				index++;
			} while(outputFile1.exists());
			
			java.io.FileOutputStream fosFlush1 = new 
				java.io.FileOutputStream(outputFile1);
			java.io.PrintStream psFlush1 = new java.io.PrintStream(fosFlush1);
			java.io.FileOutputStream fosFlush2 = new 
				java.io.FileOutputStream(outputFile2);
			java.io.PrintStream psFlush2 = new java.io.PrintStream(fosFlush2);
			
			for(int a=0; a<vUnmatchedSentences.size(); a++) {
				psFlush1.println(((AlignedSentence)vUnmatchedSentences.get(a))
					.getSource().toString());
				psFlush2.println(((AlignedSentence)vUnmatchedSentences.get(a))
					.getTarget().toString());
			}
		} catch(java.io.IOException ioe) {
			System.err.println("IO Failure: "+ioe.getMessage());
		}
	}
	
	/**
	 * Returns the vector of unmatched sentences during learning.
	 *
	 * Assumes that learning has been done for this to return any useful
	 * vector content.
	 *
	 * @return Vector sentences without matches after learning
	 */
	public Vector getUnmatchedSentences() {
		return vUnmatchedSentences;
	}
	
	public Vector readLearningTrace() {
		return vLearningTracer;
	}
	
	public void clearLearningTrace() {
		vLearningTracer = new Vector(1);
	}
	

	protected Hashtable getAlignmentInTemplates(Vector vSourceChunks1, Vector vTargetChunks1, boolean sourceIsFil){
		Vector vSourceTokens = new Vector();
		Vector vTargetTokens = new Vector();
		String strDummy = null;
		Hashtable hTemplate;
		Vector vUpdatedSChunks = new Vector(vSourceChunks1.size());
		Vector vUpdatedTChunks = new Vector(vTargetChunks1.size());
		
		TExtAligner aligner;
		
		if(sourceIsFil)
			aligner = new TExtAligner('e');
		else
			aligner = new TExtAligner('f');
			
		for(Iterator it1 = vSourceChunks1.iterator(); it1.hasNext(); ){
			Vector cSource = (Vector)it1.next();
			if(cSource.size() == 0);
				
			else
				for(Iterator it2 = cSource.iterator(); it2.hasNext(); )
					vSourceTokens.add(it2.next().toString());
			vSourceTokens.add(strDummy);
		}
		
		for(Iterator it1 = vTargetChunks1.iterator(); it1.hasNext(); ){
			Vector cTarget = (Vector)it1.next();
			if(cTarget.size() == 0);
			else
				for(Iterator it2 = cTarget.iterator(); it2.hasNext(); )
					vTargetTokens.add(it2.next().toString());
			vTargetTokens.add(strDummy);
		}

		return aligner.align(vSourceTokens, vTargetTokens, false);
	}
	
	
}